GetRawBody() is returning empty for REST requests - servicestack

I am trying to write the Raw data of my ServiceStack webservice using servicerunner. This is working for SOAP requests but for the REST request GetRawBody() is returning empty.
public override void BeforeEachRequest(IRequest requestContext, T request)
{
Logger.Write(requestContext.GetRawBody());
}

By default web servers only provide a forward-only Request Stream which you can tell ServiceStack to skip deserialization so you can read from the Request Stream by implementing IRequiresRequestStream on your Request DTO:
public class MyRequest : IRequiresRequestStream
{
Stream RequestStream { get; set; }
}
Which will inject the Request Stream instead of deserializing the Request DTO, e.g:
public class object Any(MyRequest request)
{
var requestBody = request.RequestStream.ReadFully().FromUtf8Bytes();
}
Otherwise if you want ServiceStack to deserialize the Request and you want to re-read from the Request Body later yourself you need to tell ServiceStack to buffer the Request using a pre-request filter:
appHost.PreRequestFilters.Add((httpReq, httpRes) => {
httpReq.UseBufferedStream = true;
});

Related

How do I get access to the http headers added to the dialogFlow handleRequest

I am writing a DialogFlow service.
My service receives DialogFlow fulfilment requests via an API gateway that is inserting some additional authorization headers that I need to pick up in my service.
I am using the DialogFlowApp handlerRequest method in my code but I cannot get access to the headers from the requestHandler.
The headers are added to the handleRequestMethod in the usual way
#RequestMapping(value = "/google", method = RequestMethod.POST)
public String handleGoogle(#RequestBody String form, HttpServletRequest request) {
String jsonResponse = "";
try {
jsonResponse = google.handleRequest(form, getHeadersMap(request)).get();
} catch (Exception e) {
System.out.println("Error Resposnse "+e);
}
return jsonResponse;
}
I have tried accessing the headers using something like this:
public ActionResponse genericIntentHandler(ActionRequest request) {
Argument a = request.getArgument("someval");
//Or
Object b = request.getParameter("someval");
}
Neither of these work.
Looking at the code on github, the request handler seems to add the headers to the AogRequest class
https://github.com/actions-on-google/actions-on-google-java/blob/master/src/main/kotlin/com/google/actions/api/impl/AogRequest.kt
However, the specific function called to create the class seems to do nothing with the headerMap in the constructor.
Could someone please help.

Unable to get from ServiceStack API using JsonServiceClient

I am trying to get all equipment types from my API using the following code.
client = new JsonServiceClient(environment.apiEndpoint);
var equipmentTypes = new GetEquipmentTypes();
var response = this.client.get(equipmentTypes);
I can see that it is in the network tab. The data is being transferred.
public class GetEquipmentTypeResponse
{
public IEnumerable<EquipmentType> Results { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
Is the return DTO from the API.
[Route("/api/EquipmentTypes", "GET")]
public class GetEquipmentTypes : IReturn<GetEquipmentTypeResponse>
{
}
Is the ServiceInterface used.
IEnumerable<EquipmentType> response = db.Select<EquipmentType>(x=>x.Name == request.Name);
return new GetEquipmentTypeResponse { Results = response,
ResponseStatus = new ResponseStatus { }};
Is what the API returns.
The API is written in asp.net. The client side is angular 6 (typescript).
I have attached two images, which is the request and the response given.
This is the request which is sent to the API.
This is what the API responds.
This is what I get from var response. (console.log(response))
The screenshot shows that the response is being returned fine, the Promise result is just not being awaited, try:
var response = await this.client.get(equipmentTypes);

Content-Type must be 'application/json-patch+json' JsonServiceClient ServiceStack

I'm trying to perform a patch with a JsonServiceClient to a service stack api as follows:
var patchRequest = new JsonPatchRequest
{
new JsonPatchElement
{
op = "replace",
path = "/firstName",
value = "Test"
}
};
_jsonClient.Patch<object>($"/testurl/{id}", patchRequest);
But I'm getting the following error:
Content-Type must be 'application/json-patch+json'
The error is clear. Is there a way to change the content type before perform the request for the JsonServiceClient?
This is the request POCO in the ServiceStack api:
[Api("Partial update .")]
[Route("/testurl/{Id}”, "PATCH")]
public class PartialTest : IReturn<PartialTestRequestResponse>, IJsonPatchDocumentRequest,
IRequiresRequestStream
{
[ApiMember(Name = “Id”, ParameterType = "path", DataType = "string", IsRequired = true)]
public string Id { get; set; }
public Stream RequestStream { get; set; }
}
public class PartialTestRequestResponse : IHasResponseStatus
{
public ResponseStatus ResponseStatus { get; set; }
}
Service implementation:
public object Patch(PartialTest request)
{
var dbTestRecord = Repo.GetDbTestRecord(request.Id);
if (dbTestRecord == null) throw HttpError.NotFound("Record not found.");
var patch =
(JsonPatchDocument<TestRecordPoco>)
JsonConvert.DeserializeObject(Request.GetRawBody(), typeof(JsonPatchDocument<TestRecordPoco>));
if (patch == null)
throw new HttpError(HttpStatusCode.BadRequest, "Body is not a valid JSON Patch Document.");
patch.ApplyTo(dbTestRecord);
Repo.UpdateDbTestRecord(dbTestRecord);
return new PartialTestResponse();
}
I'm using Marvin.JsonPatch V 1.0.0 library.
It's still not clear where the Exception is coming from as it's not an Error within ServiceStack. If you've registered a Custom Format or Filter that throws this error please include its impl (or a link to it) as well as the full StackTrace which will identify the source of the error.
But you should never call Patch<object> as an object return type doesn't specify what Response Type to deserialize into. Since you have an IReturn<T> marker you can just send the Request DTO:
_jsonClient.Patch(new PartialTest { ... });
Which will try to deserialize the Response in the IReturn<PartialTestRequestResponse> Response DTO. But as your Request DTO implements IRequiresRequestStream it's saying you're expecting unknown bytes that doesn't conform to a normal Request DTO, in which case you likely want to use a raw HTTP Client like HTTP Utils, e.g:
var bytes = request.Url.SendBytesToUrl(
method: HttpMethods.Path,
requestBody: jsonPatchBytes,
contentType: "application/json-patch+json",
accept: MimeTypes.Json);
You could modify the ContentType of a JSON Client using a request filter, e.g:
_jsonClient.RequestFilter = req =>
req.ContentType = "application/json-patch+json";
But it's more appropriate to use a low-level HTTP Client like HTTP Utils for non-JSON Service Requests like this.

Spring integration, Setting error-handler on http outbound gateway

If I add a custom error-handler to an int-http:outbound-gateway, the response body is not unmarshalled according to the expected-response-type, instead I only get a ResponseEntity returned. My custom error handler is pretty simple:
public class MyResponseErrorHandler extends DefaultResponseErrorHandler {
private static final Logger log = LoggerFactory.getLogger(AlmaGetUserResponseErrorHandler.class);
#Override
public boolean hasError(final ClientHttpResponse response) throws IOException {
// stop http 400 from returning true to error here.
log.debug("Request has returned error code {}", response.getStatusCode());
if (response.getBody() != null) {
String returnBody = IOUtils.toString(response.getBody(), "UTF-8");
log.debug("Checking error from response, code {}, body {}", response.getStatusCode(), returnBody);
}
return false;
}
}
As soon as I remove the error-handler, it unmarshalls the XML response into my POJO correctly.
The issue above was that the MyResponseErrorHandler class was streaming out the body content before it was being passed to the marshaller for expected-response-type. Hence the body was null and a plain ResponseEntity was returned.

ServiceStack request filter Attribute set a custom object

I am trying to write a Custom RequestFilterAttribute that would run on every service to check if the request has a a valid token. I want to return or set an object once the CanExecute method is called and forward it to the service method for further processing. Is there a way to do that in ServiceStack .
ServiceStack Request Filters lets you short-circuit a request so it does no further processing, to let a request go through you'd just ignore the request. One way to do this for specific Requests is to have them share a common interface which you can verify in your Request Filter, e.g:
public interface IValidateToken
{
string Token { get; }
}
public class MyRequest : IValidateToken
{
public string Token { get; set; }
}
Then in a Global Request Filter you can verify if the token is valid, otherwise return an error and short-circuit the request with something like:
GlobalRequestFilters.Add((httpReq, httpRes, dto) => {
var tokenRequest = dto as IValidateToken;
if (tokenRequest != null && !MyValidateToken(tokenRequest.Token))
{
httpRes.StatusCode = (int) HttpStatusCode.Forbidden;
httpRes.StatusDescription = "Token is invalid";
httpRes.EndRequest();
}
});
If the Request Token is valid the request gets processed as normal.

Resources