Returning a 201 (Created) with location header in Vapor 3 - vapor

I am trying to implement a REST-ful API using Vapor 3, and I'd prefer to use what seems like a fairly standard creation pattern in other web frameworks: I'd like the entity creation controllers to return a 201 Created response status, with a Location response header that contains the full URL of the newly-created resource.
All of the Vapor 3 documentation I can find shows a create pattern that instead returns a 200 OK status, and includes the full resource in the response body. But I can't find any examples that use a 201 response even though that tends to be the more standard REST-ful API approach in my experience.
I have found that I can manually create a 201 response in my controller, and I assume there's a way to set arbitrary headers in that response. If so, is there a convenient way of getting the full URL of the resource I've just created so that I can set a Location header in the response?
I'm sure there are ways I can "brute force" this to get what I want but I am hoping that Vapor defines an idiomatic way to do this, much like the Java and Rails frameworks I've used provide.

Since you are manually creating a response, you are right, adding an arbitrary header is simple.
I assume you are following the standard CRUD route structure, so if you have a User model, you have the following routes:
POST /users
GET /users/:user
PATCH /users/:user
DELETE /users/:user
The important part here is that we know that the URL to get the user is the URL to create a user, plus the user's ID. If this is the case, we can create a location header like this:
user.save(on: req).map { user in
let http = HTTPResponse(...)
let location = req.http.url.path + "/" + user.id.description
http.headers.replaceOrAdd(name: "Location", value: location)
return Response(http: http, container: req)
}

Related

Handle fetch in service worker but allow client to see redirect

I have a url, /users/sign_out, that is supposed log out a user and redirect them to my root url, /. I want to handle this fetch through my service worker, because I want to clean some items out of the cache before sending the user back to root. However, since the client doesn't see the redirect that happens on the fetch from the service worker, the user winds up on my splash screen but sees the pre-redirect address /users/sign_out.
Is there any way currently that I can handle the fetch and also allow the client to see the correct final url?
It appears that eventually there will be a Response.redirect() method that will allow updating a response with the final url. It looks like there is also likely to be some kind of finalURL option that would also address this case. But is there anything that I can use now? On Twitter, Jake Archibald (#jaffathecake) said I could construct a new Response myself - and I can, but even after looking at the spec and the MDN docs a bit, I still can't figure out how to specify the correct url for it.
If there is in fact a way to construct a Response object that does what I need, could someone show me how that works?
There's an example at https://github.com/GoogleChrome/samples/tree/gh-pages/service-worker/mock-responses showing how you could create a Response object and use it to respond to a fetch event.
In that case, we're creating a 200 OK response with a body, but there's nothing stopping you from creating an arbitrary response. You'd probably want a 302 Found for your use case, so you'd do something like:
var responseInit = {
status: 302,
statusText: 'Found',
headers: {
Location: '/' // Or whatever URL you want to redirect to.
}
};
var redirectResponse = new Response('', responseInit);
event.respondWith(redirectResponse);
You can include code that clears your caches inside the fetch handler before you respond to the event, and you'd obviously want to check the event.request.url value first to make sure you only respond to requests for /users/sign_out with your custom response.

File uploading using GET Method

As we all know, file uploading is most often accomplished using POST method. So, why can't the GET method be used for file uploads instead? Is there a specific prohibition against HTTP GET uploads?
GET requests may contain an entity body
RFC 2616 does not prevent an entity body as part of a GET request. This is often misunderstood because PHP muddies the waters with its poorly-named $_GET superglobal. $_GET technically has nothing to do with the HTTP GET request method -- it's nothing more than a key-value list of url-encoded parameters from the request URI query string. You can access the $_GET array even if the request was made via POST/PUT/etc. Weird, right? Not a very good abstraction, is it?
Why a GET entity body is a bad idea
So what does the spec say about the GET method ... well:
In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe."
So the important thing with GET is to make sure any GET request is safe. Still, the prohibition is
only "SHOULD NOT" ... technically HTTP still allows a GET requests to result in an action that isn't
strictly based around "retrieval."
Of course, from a semantic standpoint using a method named GET to perform an action other than
"getting" a resource doesn't make very much sense either.
When a GET entity body is flat-out wrong
Regarding idempotence, the spec says:
Methods can also have the property of "idempotence" in that (aside from error or expiration issues)
the side-effects of N > 0 identical requests is the same as for a single request. The methods GET,
HEAD, PUT and DELETE share this property.
This means that a GET method must not have differing side-effects for multiple requests for the
same resource. So, regardless of the entity body present as part of a GET request, the side-effects
must always be the same. In layman's terms this means that if you send a GET with an entity body
100 times the server cannot create 100 new resources. Whether sent once or 100 times the request must
have the same result. This severely limits the usefulness of the GET method for sending entity bodies.
When in doubt, always fall back to the safety/idempotence tests when evaluating the efficacy
of a method and its resulting side-effects.
In case of GET Method
Appends form-data into the URL in name/value pairs and length of URL is limited(3000 characters).
File content can't be put inside a URL parameter using a form.So use POST
In Get method, the value of action, appends a `?' to it, then appends the form data set, encoded using the "application/x-www-form-urlencoded" content type. The user agent then traverses the link to this URI. In this scenario, form data are restricted to ASCII codes.
So, that file upload is not possible in GET Method

Difference between "Response.PermanentRedirect" and "Delete Verb in MVC"

When using "Response.PermanentRedirect"
It will return back Http Response Code 301 which means permanent redirection to diferent location. This may not be any value for end user using the browser but for search engines it will help the search engines not to index permanently redirected urls.
Question - Does Delete Verb in MVC perform the same function ?
Post a new entity as an addition to a URI. Put replaces an entity that is identified by a URI.
Question - When performing the insert/update, the information is being submitted in both cases. Does it means in case of Insert, Post verb should be used and in case of Update Put verb should be used ?
To answer your first question :
From the RESTful API point of view DELETE must be used to remove a resource from its parent which is often a collection or store. Once a DELETE request has been processed for a given resource, the resource can no longer be found by clients. Therefore, any future attempt to retrieve the resource’s state representation, using either GET or HEAD, must result in a 404 (“Not Found”) status returned by the API.
The DELETE method has very specific semantics in HTTP, which must not be overloaded or stretched by a REST API’s design. Specifically, an API should not distort the intended meaning of DELETE by mapping it to a lesser action that leaves the resource, and its URI, available to clients.
204 (“No Content”) should be used in response to a PUT, POST, or DELETE request
Response.PermanentRedirect indicates that the REST API’s resource model has been significantly
redesigned and a new permanent URI has been assigned to the client’s requested resource.
The REST API should specify the new URI in the response’s Location header.
301 (“Moved Permanently”) should be used to relocate resources
For the Post and Put :
PUT must be used to add a new resource, with a URI specified by the client and must also be used to update or replace an already stored resource. PUT must be also used to update mutable resources while POST must be used to create a new resource in a collection.

REST - Shouldn't PUT = Create and POST = Update

Shouldn't PUT be used to Create and POST used to Update since PUT is idempotent.
That way multiple PUTs for the same Order will place only one Order?
The difference is that a PUT is for a known resource, and therefor used for updating, as stated here in rfc2616.
The fundamental difference between the POST and PUT requests is
reflected in the different meaning of the Request-URI. The URI in a
POST request identifies the resource that will handle the enclosed
entity. That resource might be a data-accepting process, a gateway to
some other protocol, or a separate entity that accepts annotations. In
contrast, the URI in a PUT request identifies the entity enclosed with
the request -- the user agent knows what URI is intended and the
server MUST NOT attempt to apply the request to some other resource.
I do see where you are coming from based on the names themselves however.
I usually look at POST as it should be the URI that will handle the content of my request (in most cases the params as form values) and thus creating a new resource, and PUT as the URI which is the subject of my request (/users/1234), a resource which already exists.
I believe the nomenclature goes back a long ways, consider the early web. One might want to POST their message to a message board, and then PUT additional content into their message at a later date.
There's no strict correspondence between HTTP methods and CRUD. This is a convention adopted by some frameworks, but it has nothing to do with REST constraints.
A PUT request asks the server to replace whatever is at the given URI with the enclosed representation, completely ignoring the current contents. A good analogy is the mv command in a shell. It creates the new file at the destination if it doesn't exist, or replaces whatever exists. In either case, it completely ignores whatever is in there. You can use this to create, but also to update something, as long as you're sending a complete representation.
POST asks the target resource to process the payload according to predefined rules, so it's the method to use for any operation that isn't already standardized by the HTTP protocol. This means a POST can do anything you want, as long as you're not duplicating functionality from other method -- for instance, using POST for retrieval when you should be using GET -- and you document it properly.
So, you can use both for create and update, depending on the exact circumstances, but with PUT you must have consistent semantics for everything in your API and you can't make partial updates, and with POST you can do anything you want, as long as you document how exactly it works.
PUT should be used for creates if and only if possible URI of the new resource is known for a client. New URI maybe advertised by the service in resource representation. For example service may provide with some kind of submit form and specify action URI on it which can be a pre populated URI of the new resource. In this case yes, if initial PUT request successfully creates resource following PUT request will only replace it.
It's ok to use POST for updates, it was never said that POST is for "create" operations only.
You are trying to correlate CRUD to HTTP, and that doesn't work. The philosophy of HTTP is different, and does not natively correspond to CRUD. The confusion arises because of REST; which does correspond to CRUD. REST uses HTTP, but with additional constraints upon what is allowed. I've prepared this Q & A to explain the HTTP approach to things:
What's being requested?
A POST requests an action upon a collection.
A PUT requests the placement of a resource into a collection.
What kind of object is named in the URI?
The URI of a POST identifies a collection.
The URI of a PUT identifies a resource (within a collection).
How is the object specified in the URI, for POST and PUT respectively?
/collectionId
/collectionId/resourceId
How much freedom does the HTTP protocol grant the collection?
With a POST, the collection is in control.
With a PUT, the requestor is in control (unless request fails).
What guarantees does the HTTP protocol make?
With a POST, the HTTP protocol does not define what is supposed to happen with the collection; the rfc states that the server should "process ... the request according to the [collection's] own specific semantics." (FYI: The rfc uses the confusing phrase "target resource" to mean "collection".) It is up to the server to decide upon a contract that defines what a POST will do.
With a PUT, the HTTP protocol requires that a response of "success" must guarantee that the collection now contains a resource with the ID and content specified by the request.
Can the operation result in the creation of a new resource within the collection?
Yes, or no, depending upon the contract. If the contract is a REST protocol, then insertion is required. When a POST creates a new resource, the response will be 201.
Yes, but that means the requestor is specifying the new ID. This is fine for bulletin boards, but problematic with databases. (Hence, for database applications, PUT will generally not insert, but only update.) When a PUT creates a new resource, the response will be 201.
Is the operation idempotent?
A POST is generally not idempotent. (The server can offer any contract it wishes, but idempotency is generally not part of that contract).
A PUT is required to be idempotent. (The state of the identified resource is idempotent. Side effects outside of that resource are allowed.)
Here is the rfc:
https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3
It depends..
you can create/update sites/records with both.
When the client is specifying the URI then PUT is the way to go.
e.g. Any Code Editor like Dreamweaver, PUT is the right protocol to use.
have also a look at this thread: put vs post in rest

In Actionscript 2 how can I get 302 redirect from a XML object?

I am working on an Actionscript 2 project - trying to use the XML object to find a url which is returned as a 302 redirect. Is there a way to do this in actionscript 2?
code:
var urlone:XML = new XML();
urlone.load("http://mydomain.com/file.py");
urlone.onLoad = function (success) {
trace("I want to print the 302 redirect url here, how do I access it?");
};
I don't think it's possible from AS2, I think the browser will redirect to the new URL automatically & just return the data from that URL. It may be possible in AS3, they added several new features such as reading HTTP headers and so on.
Perhaps what you should do is instead of returning a 302 redirect, just return the URL as a text string. Then it would be easy to read from within Flash, just use .onData instead of .onLoad so it doesn't try to parse the XML.
I don't think it's possible (at least using the XML class). It has an onHTTPStatus event handler but it seems that even with that, you'll only be able to access the status code and nothing else.

Resources