Control by response content type? - flurl

I've been handed an API that is not pretty ... i.e. it always returns a 200 but Content-Type: application/pdf when successful and Content-Type: application/text with some json in the body when it is not successful. Does flurl provide any means to control based on the Content-Type?

Found the SendAsync method which returns the Task<HttpResponseMessage> which once I have that I can access the Content-Type and all that fun stuff.

Related

Autowire request body to controller

I'm searching for a clean and simple way to autowire a POST request's body as a controller action argument, and deserialize it at the same time if application/json is set.
I've looked at events or ParamConverter, but none seem to be very adequate for this purpose.
I would use it as a shortuct to avoid using the Request object.
Eg:
POST /api/v1/admin/category HTTP/1.1
Host: localhost:8000
Authorization: Bearer token
Content-Type: application/json
Cache-Control: no-cache
{
"name": "frombody"
}
public function createCategoty(array $body) {
$body['name'] -> equals "frombody"
}
I've done that a couple of different ways recently.
joipolloi/json-validation-bundle listens for a FilterControllerEvent (a pre-controller-action hook), and then checks for an annotation that has a path to a schema to check the incoming POST request against.
I've also done it with a simple ParamConverter, where I type-hint a specific object (or specifically named array) that will receive the decoded json (assuming there is json POST content).
Either way, it is decoded from the Request's body content, and put into an action parameter.

How should I specify HTTP accept header for multipart response?

I want to communicate to a HTTP endpoint that for its multipart response, I want part 1 (or reference a content-disposition filename) to be in JSON and part 2 to be in XML, what's right way to do that?
I can include both JSON and XML but then that alone doesn't communicate my intention of wanting different formats for each part.
EDIT:
Suppose I have a service and right now it's returning something along the line of:
Content-Type: multipart/mixed; boundary=--37adc569155a4943b203e28a422cb96f
Content-Length: ...
----37adc569155a4943b203e28a422cb96f
Content-Type: application/xml; charset=utf-8
Content-Disposition: result
<Result>
...
</Result>
----37adc569155a4943b203e28a422cb96f
Content-Type: application/json; charset=utf-8
Content-Disposition: state
{ "Score": 42, ... }
----37adc569155a4943b203e28a422cb96f--
I can, and want to support passing the data back in different formats, for instance, using protocol buffer for sending the state back or using JSON for result.
I figured the right way to do it would be via the HTTP Accept header, but how do I communicate to the service that I want the state in JSON and result in protocol buffer? If the Accept header is not the way to go, what should I be using instead?
I think what you are looking to do is not defined by any of the RFCs and calls for using custom header fields. I would add headers like
X-Foo-Accept-State: application/json; charset=utf-8
X-Foo-Accept-Result: application/xml; charset=utf-8
(Where "Foo" is your company name. See elsewhere for arguments about the best way to name custom header fields.)

Using HTTP 304 in response to POST

I have a REST API that allows modification of resources using HTTP POST. It's possible that a client may submit a POST request that results in no modification of the resource. I'm thinking about using the 304 response generally used for conditional responses to indicate that the request had no effect. I haven't been able to find any examples of this being done, so I figured I'd ask here and see if anyone else is doing this or has an opinion about it.
After some consideration, I've decided to stick to a normal 200 response with the unchanged resource entity. My initial intent was to provide a concise way to indicate to the client that the resource was not modified. As I thought more about it I realized that in order to do anything useful with the 304 response, they would have to already have a cached version and in that case it would be trivial to compare the version of the cached copy with the version returned in a 200 response.
I have a REST API that allows modification of resources using HTTP POST. It's possible that a client may submit a POST request that results in no modification of the resource.
HTTP POST in the RESTful approach implies a creation of a resource, not a modification. For modification you should use HTTP PUT.
Solution of your problem is HTTP Status 200 OK when something was modified and HTTP Status 204 No Content when there was no modification. According to:
The common use case is to return 204 as a result of a PUT request, updating a resource, without changing the current content of the page displayed to the user. If the resource is created, 201 Created is returned instead. If the page should be changed to the newly updated page, the 200 should be used instead.
-- MDN web docs
For example:
-- Request
POST /people HTTP/1.1
Content-Type: application/json
{
"name": "John"
}
-- Response
HTTP/1.1 201 Created
Location: /people/1
-- Request
PUT /people/1 HTTP/1.1
Content-Type: application/json
{
"name": "John"
}
-- Response
HTTP/1.1 204 No Content
-- Request
PUT /people/1 HTTP/1.1
Content-Type: application/json
{
"name": "Robert"
}
-- Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"name": "Robert"
}

Why .Net WebApi don't detect the request contentType automatically and do auto-binding?

Why .Net WebApi don't detect the request contentType automatically and do auto-binding?
If I make a request without informing the contentType a HTTP 500 error occour:
No MediaTypeFormatter is available to read an object of type 'ExampleObject' from content with media type ''undefined''.
why not try to detect the incoming data and bind automatically?
Another case:
This request with Content-Type: application/x-www-form-urlencoded send a JSON:
User-Agent: Fiddler
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Host: localhost:10329
Content-Length: 42
Request Body:
{"Name":"qq","Email":"ww","Message":"ee"}:
My Action don't detect the JSON request data automatically in object param:
public void Create(ExampleObject example) //example is null
{
{
Instead of letting the object null why they do not try to solve it?
Then, for the binding occurs I need to send with Content-Type: application/json.
It would be best if .Net WebAPI detects the type of request data and do a auto-binding? Why not in this way?
application/x-www-form-urlencoded means you will be sending data in the x-www-form-urlencoded standard. Sending data in another standard will not work.
Sounds like what you want to do is accept multiple formats from the server.
the way http works is that the client makes a request to the server for a resource and tells the server what content types it understands. This means that the client doesnt get a response it isnt able to decode, and the server knows which responses are more appropriate on the client. For example if you are a web-browser the most appropriate content type is text/html but if you get XML you can probably do something with that too. So you would make a request with the following:
accept: text/html, application/xml
this says you prefer html but also understand XML
In your example if your client wants application/x-www-form-urlencoded but can also deal with JSON then you should do the following when making a request
accept: application/x-www-form-urlencoded, application/json
For more details see the HTTP Spec on accept headers here http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
You may also want to create a new media type formatter so your server knows how to give clients application/x-www-form-urlencoded, take a look at this blog post for more info on how to do this http://www.strathweb.com/2012/04/rss-atom-mediatypeformatter-for-asp-net-webapi/

How to cache an HTTP POST response?

I would like to create a cacheable HTTP response for a POST request.
My actual implementation responds the following for the POST request:
HTTP/1.1 201 Created
Expires: Sat, 03 Oct 2020 15:33:00 GMT
Cache-Control: private,max-age=315360000,no-transform
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 9
ETag: 2120507660800737950
Last-Modified: Wed, 06 Oct 2010 15:33:00 GMT
.........
But it looks like that the browsers (Safari, Firefox tested) are not caching the response.
In the HTTP RFC the corresponding part says:
Responses to this method are not cacheable unless the response includes appropriate Cache-Control or Expires header fields. However, the 303 (See Other) response can be used to direct the user agent to retrieve a cacheable resource.
So I think it should be cached. I know I could set a session variable and set a cookie and do a 303 redirect, but I want to cache the response of the POST request.
Is there any way to do this?
P.S.: I've started with a simple 200 OK, so it does not work.
I'd also note that caching is always optional (it's a MAY in the HTTP/1.1 RFC). Since under most circumstances, a successful POST invalidates a cache entry, it's probably simply the case that the browser caches you're looking at just don't implement caching POST responses (since this would be pretty uncommon--usually this is accomplished by formatting things as a GET, which it sounds like you've done).
Short answer: POST caching rarely makes sense. A cache may serve GET requests to a URL which is the same as that of a previous POST, whose response came with a Content-Location header containing the POST's request URI.
From rfc-7231 (http-bis, superseding rfc-2616):
Responses to POST requests are only cacheable when they include
explicit freshness information (see Section 4.2.1 of [RFC7234]).
However, POST caching is not widely implemented. For cases where an
origin server wishes the client to be able to cache the result of a
POST in a way that can be reused by a later GET, the origin server
MAY send a 200 (OK) response containing the result and a
Content-Location header field that has the same value as the POST's
effective request URI (Section 3.1.4.2).
See also Mark Nottinghams Blog:
POSTs don't deal in representations of identified state, 99 times out
of 100. However, there is one case where it does; when the server goes
out of its way to say that this POST response is a representation of
its URI, by setting a Content-Location header that's the same as the
request URI. When that happens, the POST response is just like a GET
response to the same URI; it can be cached and reused -- but only for
future GET requests.
The rfc also describes a PRG sequence which has a similar effect, allowing the response cycle to a POST to fill the cache for a subsequent GET - which is probably more widely implemented.
Can you try to change the Cache-Control to public instead of private and see if it's working?

Resources