limit supported "content-type"s + default content-type - servicestack

Using ServiceStack 3.9.2x.
Out of the box (and as seen on the metadata page) service stack comes with built-in support for a bunch of content types - xml, json, jsv, etc. What is the best way to tell ServiceStack to limit the set of supported content. For example my service only knows how to speak JSON and I don't want ServiceStack to honor requests that sport "Content-type: application/xml" or "Accept: application/xml" headers. In said case I would like ServiceStack to respond with a 406 (Not Acceptable) response, ideally including in the body the set of supported content (per HTTP 1.1 spec).
Also how does ServiceStack decide what the default type of the content is for requests that do not sport an Accept or Content-Type header (I think I am seeing it render HTML now)? Is there a way to tell ServiceStack to assume a specific content type in these cases?

See this answer to find out how to set the default content type in ServiceStack: ServiceStack default format
You can use a Request Filter to detect the requested content type with:
httpReq.ResponseContentType
In your global request filter you can choose to allow it (do nothing) or write directly to the response, e.g. 406 with list of supported content as you wish.
ServiceStack order of operations
The Implementation architecture diagram shows a visual cue of the order of operations that happens in ServiceStack. Where:
EndointHostConfig.RawHttpHandlers are executed before anything else, i.e. returning any ASP.NET IHttpHandler by-passes ServiceStack completely.
The IAppHost.PreRequestFilters gets executed before the Request DTO is deserialized
Request Filter Attributes with Priority < 0 gets executed
Then any Global Request Filters get executed
Followed by Request Filter Attributes with Priority >= 0
Action Request Filters (New API only)
Then your Service is executed
Action Response Filters (New API only)
Followed by Response Filter Attributes with Priority < 0
Then Global Response Filters
Followed by Response Filter Attributes with Priority >= 0
Any time you close the Response in any of your filters, i.e. httpRes.Close() the processing of the response is short-circuited and no further processing is done on that request.

Related

How to avoid loading email's content using spring integration mail

I am using spring integration mail (5.3.1 release)
I have a flow:
IntegrationFlows
.from(Mail
.imapIdleAdapter(imapAdapter)
)
.filter()
.filter()
...
.filter()
.handle(service1)
.get();
I want an email content to be loaded in service1.
I don't want to load email's content until it passes all filters.
My filters need to know only email headers.
I tried to use DefaultMailHeaderMapper but email's content is loaded anyway. I can see it in logs using "mail.debug"=true.
I was debugging and according to source of AbstractMailReceiver#receive, MimeMessage's content will be always loaded because e.g new IntegrationMimeMessage() uses MimeMessage(MimeMessage message) constructor that loads a content.
Is there any way to configure mail adapter to not load an email's content?
Thank you!
See docs: https://docs.spring.io/spring-integration/docs/current/reference/html/mail.html#mail-inbound. Especially this part:
tarting with version 5.2, the autoCloseFolder option is provided on the mail receiver. Setting it to false doesn’t close the folder automatically after a fetch, but instead an IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE header (see MessageHeaderAccessor API for more information) is populated into every message to producer from the channel adapter.
And then take a look into the next section: https://docs.spring.io/spring-integration/docs/current/reference/html/mail.html#mail-mapping
So, to avoid eager content loading you should abandon the header mapper and don't close the folder automatically. This way the whole MimeMessage is sent as a payload. You probably won't be able to perform your filtering logic against headers because the content of the message is not fetched therefore we don't know what headers are there in MimeMessage. However you can try to get access to them from your filters, but already against the payload - not headers.

How to Use HTTP Receive GET Message in Orchestration?

I have set up a HTTP Receive (req-response) adapter and the message appears to be getting to the message box. When I create an orchestration using a direct bound logical port, I am getting the message but everything I have tried to read the message body has failed (using passthrough pipeline, XML pipeline with allow unrecognized files = true) but I get exceptions any time I try to use the incoming message (message assignments, sending the message to a custom module to try to read the part(s)).
Rather than go into details on exceptions, can anyone point to instructions on what the proper way to access/use the body of the HTTP Get messages within an orchestration? To explain what I am trying to do, I want to take the query string (body) and send it verbatim to another orchestration for processing, so I simply want to extract the body (query string) from the message.
For a GET request without a body you need to use the WCF-WebHttp adapter rather than the deprecated BTSHTTPReceive.dll
With the WCF-WebHttp you can use the Variable Mapping to populate message context properties with the URI parameters.
So the answer was to NOT use the HTTP adapter for GET requests. I did not realize the HTTP adapter has effectively been deprecated. For basic GET requests I had to switch to the WCF-WebHTTP adapter and make sure to include the property in the property schema and then make sure to set the schema in the variable mapping as the property schema, not the message type schema of the incoming message. I wish the Microsoft documentation was more clear that the HTTP adapter cannot be used for very basic GET requests in which a body is not provided in the request.

Which AMP extensions can fetch a response from an endpoint?

What AMP extensions can be used to get a response from the server in the form of variable that can be used later, such as in a template or as a parameter to an attribute?
amp-access
The authorization endpoint of amp-access can return "a free-form JSON object":
Here’s a small list of possible ideas for properties that can be returned from the Authorization endpoint:
Metering info: maximum allowed number of views and current number of views.
Whether the Reader is logged in or a subscriber.
A more detailed type of the subscription: basic, premium
Geo: country, region, custom publication region
amp-form
amp-form "allows publishers to render the responses using Extended Templates". The response is expected to be a valid JSON Object. Try the "Hiding input fields after success" demo in the amp-form sample to see it in action.
amp-list
amp-list fetches "content dynamically from a CORS JSON endpoint and renders it using a supplied template". The response must be a JSON object that contains an array property "items".
In addition to {{variable}} substitutions in Mustache templates, you can also use AUTHDATA(variable) elsewhere.
amp-live-list (not quite)
amp-live-list is a "wrapper and minimal UI for content that updates live in the client instance as new content is available in the source document". The page will re-fetch itself, giving the server a change to send new content. If new content is found, AMP will populate a <div items> element with the new (HTML) items. You can't use that as a variable.
It's name doesn't really suggest it, but I think you want AMP-list
https://github.com/ampproject/amphtml/blob/master/extensions/amp-list/amp-list.md
Fetches content dynamically from a CORS JSON endpoint and renders it using a supplied template.

Jersey2 ContainerRequestFilter not executing before autentication

I am trying to get security working with my jersey2 web app.
I register RolesAllowedDynamicFeature and my Request filter with AUTHENTICATION priority in my ResourceConfig
packages("example.jersey");
register(MyRequestFilter.class, Priorities.AUTHENTICATION);
register(RolesAllowedDynamicFeature.class);
I added #RolesAllowed to the method
#RolesAllowed("quinn")
#GET
#Path("/")
public Response getIt(#Context UriInfo uriInfo) {
return Response.ok().entity(service.get()).build();
}
In my request filter I set my security context
SecurityContext securityContext = containerRequestContext.getSecurityContext();
containerRequestContext.setSecurityContext(new MySecurityContext("gary", securityContext));
When I call the method from postman I get a 403 - Forbidden
I added logging to my request filter to see when it is called. It is NOT called.
If I remove the #RolesAllowed from the web method it does call the request filter.
It seems the Priorities.AUTHENTICATION is not making a difference.
Is there anything I'm missing?
Your filter is implemented as a post-matching filter. It means that the filters would be applied only after a suitable resource method has been selected to process the actual request i.e. after request matching happens. Request matching is the process of finding a resource method that should be executed based on the request path and other request parameters.
#RolesAllowed blocks the selection of the particular resource method giving you the 'not executing' behavior you mentioned.
You have two options... using #PreMatching as explained here.
Or, use custom annotations as explained on a similar question.

azure method blows up if the records does not exist

I am using this method from the azure mobile services tutorial:
await todoTable.LookupAsync(id). I have 2 rows in a table of id 1,2.
If i do await todoTable.LookupAsync(1), it works and return the record. If i do
await todoTable.LookupAsync(8) to see how it's going to handle null, it just blows up with Not Found exception.
Thanks for help on this.
NULL would mean there is a record for id = 8, but its value is `NULL'. But in your case you do not have a record. Which is different.
What you observe is what you should observe if you do not have a record.
And this is a standard for REST based HTTP services. If record is not there, you get an HTTP 404 from the service.
Azure mobile services is nothing more than a combination of Web API and a wrapping (plumbing) code for your application. And every Web API call to a non-existent record would result into an HTTP 404 error.
And as already said in the comments, you should wrap your code around try - catch blocks and inspect the exception.
In .NET 4.5/4.6 there is new HttpClient type along with HttpResponseMessage and HttpRequestMessatge. The former has EnsureSuccessStatusCode() method. Which, if called will trigger exception.
In the older versions of the Framework there WebClient class, which would throw an exception if the HTTP status code is not 200.
So, again, at the end - you observe absolutely normal behavoir. Just have to read a little more about HTTP REST services, HTTP VERBS and HTTP Status Codes. Then also understand how the particular framework you use (.NET) handles the HTTP Status Codes.

Resources