Related
I have tried everything but I cant seem to fix this issue that is happening for only one client behind a corporate proxy/firewall. Our Silverlight application connects to Amazon S3 for downloading/Uploading some documents. On one client and one client only it returns a 407 error and after that the application fails to save anything.
Inner Exception:
System.ServiceModel.ProtocolException: [UnexpectedHttpResponseCode]
Arguments: 407,Proxy Authentication Required
We had something similar at a different client but there was more of a CORS issue. to resolve this I used cloud-front to fake a sub-domain that then accesses the S3 bucket and it solved the issue. I was hoping it would fix it with this client as well but it didnt.
I have tried adding this code to web.config as suggested by a lot of answers
<system.net>
<defaultProxy useDefaultCredentials="true" >
</defaultProxy>
</system.net>
I have read articles about passing a proxy headers with basis authentication using username and password but I am not sure how this would help us. The Proxy server is used by client and any authentication it requires is outside our domain.
**Additional Information**
The Silverlight code references 2 services. One is our wcf service that retrieves all the data for the application. One is The Amazon S3 service that uses the amazon Soap api, the endpoint for which is at http://s3.amazonaws.com/doc/2006-03-01/AmazonS3.wsdl?
If I go into our app and only use part of the system that dont make any calls to the Amazon S3 api the application works fine. As soon as I go to a part of the system that makes a call to the S3, the problem starts. funny enough the call to S3 goes fine and I can retrieve the doc fine but then any calls to our wcf service return 407.
Any ideas?
**Update 2**
Based on comments from Elliot Nelson I check the stack we were using for making http requests in our application. Turns out we are using client http for both http and https requests by default. Here is the code we have in the App.xaml constructor
public App()
{
Startup += Application_Startup;
UnhandledException += Application_UnhandledException;
InitializeComponent();
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
}
Now, to understand the differences between clienthttp and browserhttp and when to use them. Also, the potential impacts/issues of switching to browserhttp.
**Update 3**
Is there a way to request browsers to run your in-browser Silverlight application in trusted mode and would it help bypass this issue?
(Answer #2)
So, most likely (for corporate environments like this network), almost nothing can be done without whatever custom proxy settings are set in IE, usually pushed by corporate policy. To take advantage of these proxy settings, you want to use WebRequestCreator.BrowserHttp, which automatically uses the browser's default settings when making requests.
There's a table of the differences between these two clients available in the Microsoft docs. I'm guessing you were using something (maybe setting custom headers or reading the raw response body) that wasn't supported in BrowserHttp.
For security reasons, you can't "ask" the browser what its proxy settings are and use them, so this is a tricky situation. You can specify Browser vs Client handling by domain, or even for a specific request (the same page above describes how); you may be able in this case to get away with just using ClientHttp for your service calls and BrowserHttp for your S3 calls, and avoid the problem altogether!
For next steps, I'd try that approach; if it doesn't work, I'd try switching wholesale to BrowserHttp just to see if it bypasses the proxy issue (there's almost no chance the application will actually work, since you're probably using ClientHttp-only options).
Long term, you may want to consider making changes to your services so they are usable by a BrowserHttp-only application (this would require you to be pretty basic in your requests/responses, but using only BrowserHttp would be a guarantee you'd work in pretty much any corp network).
Running in trusted mode is probably a group policy thing which would require their AD admins to approve / whitelist your app.
I think the underlying issue you are facing is that the proxy requires NTLM authentication and for whatever reason the browser declines to provide your app with that context.
One way to prove that it's an NTLM auth issue is to test with curl - get it to make a req through the proxy, then it should be a bit easier to code to. EG the following curl will get you through 99% of Windows corporate proxies (assuming the proxy is at proxy-host.corp:3128):
C:\> curl.exe -v --proxy proxy-host:3128 --proxy-user : --proxy-ntlm https://www.google.com
NOTE The --proxy-user : tells curl to use the current user session to perform the NTLM challenge.
So if you can get the client to run that, you can at least identify that NTLM works, then it's a just a matter of getting the app to perform the NTLM challenge using the default credentials (which may or may not be provided by the browser session)
Since you described this as a silverlight application, I'm going to assume you can't use classic browser-proxy troubleshooting like "move browser to public network" or "try a different browser", to isolate the problem.
You should try to isolate the proxy server, and have the customer use the required proxy-auth.
The application is making request, but it might be intercepted by a transparent proxy, or the result might be coming from what you consider a web server.
In the early days, the 401 error was pretty strictly associated with web-auth, and 407 was for proxy-auth.
Architecturally, the separation is a convenience, a web server can have both web server, proxy, and reverse-proxy behaviors.
What happens is your customer's environment is making a web connection to the destination, but it receives a HTTP 407 status from some host, probably their network, or sometimes the provider. Almost certainly the request is received not forwarded. The HTTP client your application lives in needs to provide the credentials that host requires. Companies have environments that are complex enough where often your customer will say this is the first time they have heard of this (some proxy-auth is also dynamic or destination specific).
Also, in some corporate environments, the operator will allow temporary or permanent white-listing from the proxy-auth service. You should see if they can do this, even temporarily, to confirm there aren't going to be other problems.
In the end, it sounds like your application might not robustly support proxy-auth, or the proxy-auth type they use in their environment.
I am looking for a way to wrap APIs around default functions in my PHP-based web applications, databases and CMSs.
I have looked around and found several "skeleton" frameworks. In addition to the answers in my question, there is Tonic, a REST framework I like because it is very lightweight.
I like REST the best for its simplicity, and would like to create an API architecture based on it. I'm trying to get my head around the basic principles and have not fully understood it yet. Therefore, a number of questions.
1. Am I understanding it right?
Say I have a resource "users". I could set up a number of URIs like so:
/api/users when called with GET, lists users
/api/users when called with POST, creates user record
/api/users/1 when called with GET, shows user record
when called with PUT, updates user record
when called with DELETE, deletes user record
is this a correct representation of a RESTful architecture so far?
2. I need more verbs
Create, Update and Delete may be enough in theory, but in practice I will have the need for a lot more verbs. I realize these are things that could be embedded in an update request, but they are specific actions that can have specific return codes and I wouldn't want to throw them all into one action.
Some that come to mind in the user example are:
activate_login
deactivate_login
change_password
add_credit
how would I express actions such as those in a RESTful URL architecture?
My instinct would be to do a GET call to a URL like
/api/users/1/activate_login
and expect a status code back.
That deviates from the idea of using HTTP verbs, though. What do you think?
3. How to return error messages and codes
A great part of REST's beauty stems from its use of standard HTTP methods. On an error, I emit a header with a 3xx,4xx or 5xx error status code. For a detailed error description, I can use the body (right?). So far so good. But what would be the way to transmit a proprietary error code that is more detailed in describing what went wrong (e.g. "failed to connect to database", or "database login wrong")? If I put it into the body along with the message, I have to parse it out afterwards. Is there a standard header for this kind of thing?
4. How to do authentication
What would a API key based authentication following REST principles look like?
Are there strong points against using sessions when authenticating a REST client, other than that it's a blatant violation of the REST principle? :) (only half kidding here, session based authentication would play well with my existing infrastructure.)
I noticed this question a couple of days late, but I feel that I can add some insight. I hope this can be helpful towards your RESTful venture.
Point 1: Am I understanding it right?
You understood right. That is a correct representation of a RESTful architecture. You may find the following matrix from Wikipedia very helpful in defining your nouns and verbs:
When dealing with a Collection URI like: http://example.com/resources/
GET: List the members of the collection, complete with their member URIs for further navigation. For example, list all the cars for sale.
PUT: Meaning defined as "replace the entire collection with another collection".
POST: Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation.
DELETE: Meaning defined as "delete the entire collection".
When dealing with a Member URI like: http://example.com/resources/7HOU57Y
GET: Retrieve a representation of the addressed member of the collection expressed in an appropriate MIME type.
PUT: Update the addressed member of the collection or create it with the specified ID.
POST: Treats the addressed member as a collection in its own right and creates a new subordinate of it.
DELETE: Delete the addressed member of the collection.
Point 2: I need more verbs
In general, when you think you need more verbs, it may actually mean that your resources need to be re-identified. Remember that in REST you are always acting on a resource, or on a collection of resources. What you choose as the resource is quite important for your API definition.
Activate/Deactivate Login: If you are creating a new session, then you may want to consider "the session" as the resource. To create a new session, use POST to http://example.com/sessions/ with the credentials in the body. To expire it use PUT or a DELETE (maybe depending on whether you intend to keep a session history) to http://example.com/sessions/SESSION_ID.
Change Password: This time the resource is "the user". You would need a PUT to http://example.com/users/USER_ID with the old and new passwords in the body. You are acting on "the user" resource, and a change password is simply an update request. It's quite similar to the UPDATE statement in a relational database.
My instinct would be to do a GET call
to a URL like
/api/users/1/activate_login
This goes against a very core REST principle: The correct usage of HTTP verbs. Any GET request should never leave any side effect.
For example, a GET request should never create a session on the database, return a cookie with a new Session ID, or leave any residue on the server. The GET verb is like the SELECT statement in a database engine. Remember that the response to any request with the GET verb should be cache-able when requested with the same parameters, just like when you request a static web page.
Point 3: How to return error messages and codes
Consider the 4xx or 5xx HTTP status codes as error categories. You can elaborate the error in the body.
Failed to Connect to Database: / Incorrect Database Login: In general you should use a 500 error for these types of errors. This is a server-side error. The client did nothing wrong. 500 errors are normally considered "retryable". i.e. the client can retry the same exact request, and expect it to succeed once the server's troubles are resolved. Specify the details in the body, so that the client will be able to provide some context to us humans.
The other category of errors would be the 4xx family, which in general indicate that the client did something wrong. In particular, this category of errors normally indicate to the client that there is no need to retry the request as it is, because it will continue to fail permanently. i.e. the client needs to change something before retrying this request. For example, "Resource not found" (HTTP 404) or "Malformed Request" (HTTP 400) errors would fall in this category.
Point 4: How to do authentication
As pointed out in point 1, instead of authenticating a user, you may want to think about creating a session. You will be returned a new "Session ID", along with the appropriate HTTP status code (200: Access Granted or 403: Access Denied).
You will then be asking your RESTful server: "Can you GET me the resource for this Session ID?".
There is no authenticated mode - REST is stateless: You create a session, you ask the server to give you resources using this Session ID as a parameter, and on logout you drop or expire the session.
Simply put, you are doing this completely backward.
You should not be approaching this from what URLs you should be using. The URLs will effectively come "for free" once you've decided upon what resources are necessary for your system AND how you will represent those resources, and the interactions between the resources and application state.
To quote Roy Fielding
A REST API should spend almost all of
its descriptive effort in defining the
media type(s) used for representing
resources and driving application
state, or in defining extended
relation names and/or
hypertext-enabled mark-up for existing
standard media types. Any effort spent
describing what methods to use on what
URIs of interest should be entirely
defined within the scope of the
processing rules for a media type
(and, in most cases, already defined
by existing media types). [Failure
here implies that out-of-band
information is driving interaction
instead of hypertext.]
Folks always start with the URIs and think this is the solution, and then they tend to miss a key concept in REST architecture, notably, as quoted above, "Failure here implies that out-of-band information is driving interaction instead of hypertext."
To be honest, many see a bunch of URIs and some GETs and PUTs and POSTs and think REST is easy. REST is not easy. RPC over HTTP is easy, moving blobs of data back and forth proxied through HTTP payloads is easy. REST, however, goes beyond that. REST is protocol agnostic. HTTP is just very popular and apt for REST systems.
REST lives in the media types, their definitions, and how the application drives the actions available to those resources via hypertext (links, effectively).
There are different view about media types in REST systems. Some favor application specific payloads, while others like uplifting existing media types in to roles that are appropriate for the application. For example, on the one hand you have specific XML schemas designed suited to your application versus using something like XHTML as your representation, perhaps through microformats and other mechanisms.
Both approaches have their place, I think, the XHTML working very well in scenarios that overlap both the human driven and machine driven web, whereas the former, more specific data types I feel better facilitate machine to machine interactions. I find the uplifting of commodity formats can make content negotiation potentially difficult. "application/xml+yourresource" is much more specific as a media type than "application/xhtml+xml", as the latter can apply to many payloads which may or may not be something a machine client is actually interested in, nor can it determine without introspection.
However, XHTML works very well (obviously) in the human web where web browsers and rendering is very important.
You application will guide you in those kinds of decisions.
Part of the process of designing a REST system is discovering the first class resources in your system, along with the derivative, support resources necessary to support the operations on the primary resources. Once the resources are discovered, then the representation of those resources, as well as the state diagrams showing resource flow via hypertext within the representations because the next challenge.
Recall that each representation of a resource, in a hypertext system, combines both the actual resource representation along with the state transitions available to the resource. Consider each resource a node in a graph, with the links being the lines leaving that node to other states. These links inform clients not only what can be done, but what is required for them to be done (as a good link combines the URI and the media type required).
For example, you may have:
<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
Your documentation will talk about the rel field named "users", and the media type of "application/xml+youruser".
These links may seem redundant, they're all talking to the same URI, pretty much. But they're not.
This is because for the "users" relation, that link is talking about the collection of users, and you can use the uniform interface to work with the collection (GET to retrieve all of them, DELETE to delete all of them, etc.)
If you POST to this URL, you will need to pass a "application/xml+usercollection" document, which will probably only contain a single user instance within the document so you can add the user, or not, perhaps, to add several at once. Perhaps your documentation will suggest that you can simply pass a single user type, instead of the collection.
You can see what the application requires in order to perform a search, as defined by the "search" link and it's mediatype. The documentation for the search media type will tell you how this behaves, and what to expect as results.
The takeaway here, though, is the URIs themselves are basically unimportant. The application is in control of the URIs, not the clients. Beyond a few 'entry points', your clients should rely on the URIs provided by the application for its work.
The client needs to know how to manipulate and interpret the media types, but doesn't much need to care where it goes.
These two links are semantically identical in a clients eyes:
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>
So, focus on your resources. Focus on their state transitions in the application and how that's best achieved.
re 1: This looks fine so far. Remember to return the URI of the newly created user in a "Location:" header as part of the response to POST, along with a "201 Created" status code.
re 2: Activation via GET is a bad idea, and including the verb in the URI is a design smell. You might want to consider returning a form on a GET. In a Web app, this would be an HTML form with a submit button; in the API use case, you might want to return a representation that contains a URI to PUT to to activate the account. Of course you can include this URI in the response on POST to /users, too. Using PUT will ensure your request is idempotent, i.e. it can safely be sent again if the client isn't sure about success. In general, think about what resources you can turn your verbs into (sort of "nounification of verbs"). Ask yourself what method your specific action is most closely aligned with. E.g. change_password -> PUT; deactivate -> probably DELETE; add_credit -> possibly POST or PUT. Point the client to the appropriate URIs by including them in your representations.
re 3. Don't invent new status codes, unless you believe they're so generic they merit being standardized globally. Try hard to use the most appropriate status code available (read about all of them in RFC 2616). Include additional information in the response body. If you really, really are sure you want to invent a new status code, think again; if you still believe so, make sure to at least pick the right category (1xx -> OK, 2xx -> informational, 3xx -> redirection; 4xx-> client error, 5xx -> server error). Did I mention that inventing new status codes is a bad idea?
re 4. If in any way possible, use the authentication framework built into HTTP. Check out the way Google does authentication in GData. In general, don't put API keys in your URIs. Try to avoid sessions to enhance scalability and support caching - if the response to a request differs because of something that has happened before, you've usually tied yourself to a specific server process instance. It's much better to turn session state into either client state (e.g. make it part of subsequent requests) or make it explicit by turning it into (server) resource state, i.e. give it its own URI.
1. You've got the right idea about how to design your resources, IMHO. I wouldn't change a thing.
2. Rather than trying to extend HTTP with more verbs, consider what your proposed verbs can be reduced to in terms of the basic HTTP methods and resources. For example, instead of an activate_login verb, you could set up resources like: /api/users/1/login/active which is a simple boolean. To activate a login, just PUT a document there that says 'true' or 1 or whatever. To deactivate, PUT a document there that is empty or says 0 or false.
Similarly, to change or set passwords, just do PUTs to /api/users/1/password.
Whenever you need to add something (like a credit) think in terms of POSTs. For example, you could do a POST to a resource like /api/users/1/credits with a body containing the number of credits to add. A PUT on the same resource could be used to overwrite the value rather than add. A POST with a negative number in the body would subtract, and so on.
3. I'd strongly advise against extending the basic HTTP status codes. If you can't find one that matches your situation exactly, pick the closest one and put the error details in the response body. Also, remember that HTTP headers are extensible; your application can define all the custom headers that you like. One application that I worked on, for example, could return a 404 Not Found under multiple circumstances. Rather than making the client parse the response body for the reason, we just added a new header, X-Status-Extended, which contained our proprietary status code extensions. So you might see a response like:
HTTP/1.1 404 Not Found
X-Status-Extended: 404.3 More Specific Error Here
That way a HTTP client like a web browser will still know what to do with the regular 404 code, and a more sophisticated HTTP client can choose to look at the X-Status-Extended header for more specific information.
4. For authentication, I recommend using HTTP authentication if you can. But IMHO there's nothing wrong with using cookie-based authentication if that's easier for you.
REST Basics
REST have an uniform interface constraint, which states that the REST client must rely on standards instead of application specific details of the actual REST service, so the REST client won't break by minor changes, and it will probably be reusable.
So there is a contract between the REST client and the REST service. If you use HTTP as the underlying protocol, then the following standards are part of the contract:
HTTP 1.1
method definitions
status code definitions
cache control headers
accept and content-type headers
auth headers
IRI (utf8 URI)
body (pick one)
registered application specific MIME type, e.g. maze+xml
vendor specific MIME type, e.g. vnd.github+json
generic MIME type with
application specific RDF vocab, e.g. ld+json & hydra, schema.org
application specific profile, e.g. hal+json & profile link param (I guess)
hyperlinks
what should contain them (pick one)
sending in link headers
sending in a hypermedia response, e.g. html, atom+xml, hal+json, ld+json&hydra, etc...
semantics
use IANA link relations and probably custom link relations
use an application specific RDF vocab
REST has a stateless constraint, which declares that the communication between the REST service and client must be stateless. This means that the REST service cannot maintain the client states, so you cannot have a server side session storage. You have to authenticate every single request. So for example HTTP basic auth (part of the HTTP standard) is okay, because it sends the username and password with every request.
To answer you questions
Yes, it can be.
Just to mention, the clients do not care about the IRI structure, they care about the semantics, because they follow links having link relations or linked data (RDF) attributes.
The only thing important about the IRIs, that a single IRI must identify only a single resource. It is allowed to a single resource, like an user, to have many different IRIs.
It is pretty simple why we use nice IRIs like /users/123/password; it is much easier to write the routing logic on the server when you understand the IRI simply by reading it.
You have more verbs, like PUT, PATCH, OPTIONS, and even more, but you don't need more of them... Instead of adding new verbs you have to learn how to add new resources.
deactivate_login -> PUT /login/active false
change_password -> PUT /user/xy/password "newpass"
add_credit -> POST /credit/raise {details: {}}
(The login does not make sense from REST perspective, because of the stateless constraint.)
Your users do not care about why the problem exist. They want to know only if there is success or error, and probably an error message which they can understand, for example: "Sorry, but we weren't able to save your post.", etc...
The HTTP status headers are your standard headers. Everything else should be in the body I think. A single header is not enough to describe for example detailed multilingual error messages.
The stateless constraint (along with the cache and layered system constraints) ensures that the service scales well. You surely don't wan't to maintain millions of sessions on the server, when you can do the same on the clients...
The 3rd party client gets an access token if the user grants access to it using the main client. After that the 3rd party client sends the access token with every request. There are more complicated solutions, for example you can sign every single request, etc. For further details check the OAuth manual.
Related literature
Architectural Styles and the Design of Network-based Software Architectures
Dissertation of Roy Thomas Fielding (author of REST)
2000, University of California, Irvine
Third Generation Web APIs - Bridging the Gap between REST and Linked Data
Dissertation of Markus Lanthaler (co-author of JSON-LD and author of Hydra)
2014, Graz University of Technology, Austria
For the examples you stated I'd use the following:
activate_login
POST /users/1/activation
deactivate_login
DELETE /users/1/activation
change_password
PUT /passwords (this assumes the user is authenticated)
add_credit
POST /credits (this assumes the user is authenticated)
For errors you'd return the error in the body in the format that you got the request in, so if you receive:
DELETE /users/1.xml
You'd send the response back in XML, the same would be true for JSON etc...
For authentication you should use http authentication.
Use post when you don't know how the new resource URI would look like (you create new user, application would assign the new user it's id), PUT for updating or creating resources that you know how are they going to be represented (example: PUT /myfiles/thisismynewfile.txt)
return the error description in message body
You can use HTTP authentication (if it's enough)
Web services should be stateles
I would suggest (as a first pass) that PUT should only be used for updating existing entities. POST should be used for creating new ones. i.e.
/api/users when called with PUT, creates user record
doesn't feel right to me. The rest of your first section (re. verb usage) looks logical, however.
Verbose, but copied from the HTTP 1.1 method specification at http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
9.3 GET
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process.
The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring multiple requests or transferring data already held by the client.
The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A partial GET requests that only part of the entity be transferred, as described in section 14.35. The partial GET method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed without transferring data already held by the client.
The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in section 13.
See section 15.1.3 for security considerations when used for forms.
9.5 POST
The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform method to cover the following functions:
- Annotation of existing resources;
- Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
- Providing a block of data, such as the result of submitting a
form, to a data-handling process;
- Extending a database through an append operation.
The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.
The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.
If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).
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.
POST requests MUST obey the message transmission requirements set out in section 8.2.
See section 15.1.3 for security considerations.
9.6 PUT
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases.
If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.
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. If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying "the current version" which is separate from the URI identifying each particular version. In this case, a PUT request on a general URI might result in several other URIs being defined by the origin server.
HTTP/1.1 does not define how a PUT method affects the state of an origin server.
PUT requests MUST obey the message transmission requirements set out in section 8.2.
Unless otherwise specified for a particular entity-header, the entity-headers in the PUT request SHOULD be applied to the resource created or modified by the PUT.
9.7 DELETE
The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location.
A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.
If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.
About REST return codes: it is wrong to mix HTTP protocol codes and REST results.
However, I saw many implementations mixing them, and many developers may not agree with me.
HTTP return codes are related to the HTTP Request itself. A REST call is done using a Hypertext Transfer Protocol request and it works at a lower level than invoked REST method itself. REST is a concept/approach, and its output is a business/logical result, while HTTP result code is a transport one.
For example, returning "404 Not found" when you call /users/ is confuse, because it may mean:
URI is wrong (HTTP)
No users are found (REST)
"403 Forbidden/Access Denied" may mean:
Special permission needed. Browsers can handle it by asking the user/password. (HTTP)
Wrong access permissions configured on the server. (HTTP)
You need to be authenticated (REST)
And the list may continue with '500 Server error" (an Apache/Nginx HTTP thrown error or a business constraint error in REST) or other HTTP errors etc...
From the code, it's hard to understand what was the failure reason, a HTTP (transport) failure or a REST (logical) failure.
If the HTTP request physically was performed successfully it should always return 200 code, regardless is the record(s) found or not. Because URI resource is found and was handled by the http server. Yes, it may return an empty set. Is it possible to receive an empty web-page with 200 as http result, right?
Instead of this you may return 200 HTTP code and simply a JSON with an empty array/object, or to use a bool result/success flag to inform about the performed operation status.
Also, some internet providers may intercept your requests and return you a 404 http code. This does not means that your data are not found, but it's something wrong at transport level.
From Wiki:
In July 2004, the UK telecom provider BT Group deployed the Cleanfeed
content blocking system, which returns a 404 error to any request for
content identified as potentially illegal by the Internet Watch
Foundation. Other ISPs return a HTTP 403 "forbidden" error in the same
circumstances. The practice of employing fake 404 errors as a means to
conceal censorship has also been reported in Thailand and Tunisia. In
Tunisia, where censorship was severe before the 2011 revolution,
people became aware of the nature of the fake 404 errors and created
an imaginary character named "Ammar 404" who represents "the invisible
censor".
I've been tasked (I'm not a web developer) with creating something (a web service "client") that will connect to a web service, retrieve a list of files (url's) and then download them (HTTP Post) for further processing. I guess anything like a command line app that I can schedule to run daily will do (but I'm open to suggestions).
I have documentation for the web service, it uses SOAP 1.1 which I am somewhat familiar with (used it in a few web pages, but that was classic asp). They are even offering a WSDL to download in order to generate proxy classes, or you can create your own.
Below is the description of the objects that the WSDL creates:
There are six software entities that you will need to implement in your web service client. If your development environment automatically generates these from the WSDL, they will have the following names and purposes:
DownloadSvc
Response
ResponseCodeEnum
UserType
CertificationEnum
FileFormat.
DownloadSvc Class – This is the central object you will use. It implements the majority of the behavior needed to login to the service, to check the availability of a download and to obtain the download URL. For example, it has a Login and a GetURLS method. This class supports both full and change list (“delta”) downloads.
Response Class – Most methods of the DownloadSvc return this Response object. The fields in Response are as follows:
The Response.code field always describes the success or failure of a method call.
The Response.value field sometimes contains additional information.The remaining four items are simple enumerations that define the allowable values in the fields passed from or to the service.
ResponseCodeEnum – Describes the possible values of the Response.code field. For example, it may return a code of LoginOK or DownloadOK for successful calls, or an error-specific code for failures. You can see the specific code values listed in the sample SOAP responses in the SOAP Appendix.
UserType – Only used with the Login method. It identifies which password is being used to login: your Representative password or your Downloader password.
CertificationEnum – An enumeration that you use to certify your agreement with the FTC’s conditions for downloading these phone number files as specified on the download full or download change page.
FileFormat – An enumeration that lets you select a flat text file or an XML file format.
Here's my question: where do I start in Visual Studio? What type of project do I need? Thank you!
I am wanting to expose a restful web service for posting and retrieving data, this may be consumed by mobile devices or a web site.
Now the actual creation of the service isn't a problem, what does seem to be a problem is communicating from a different domain.
I have made a simple example service deployed on the ASP.NET development server, which just exposes a simple POST action to send a request with JSON content. Then I have created a simple web page using jquery ajax to send some dummy data over, yet I believe I am getting stung with the same origin policy.
Is this a common thing, and how do you get around it? Some places have mentioned having a proxy on the domain that you always request a get to, but then you cannot use it in a restful manner...
So is this a common issue with a simple fix? As there seem to be plenty of restful services out there that allow 3rd parties to use their service...
How exactly are you "getting stung with the same origin policy"? From your description, I don't see how it could be relevant. If yourdomain.com/some-path/defined-request.json returns a certain JSON response, then it will return that response regardless of what is requesting the file, unless you have specifically defined required credentials that are not satisfied.
Here is an example of such a web service. It will return the same JSON object regardless of from where the request is made: http://maps.googleapis.com/maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&sensor=true
Unless I am misunderstanding you (in which case you should clarify your actual problem), the same origin policy doesn't really seem to apply here.
Update Re: Comment
"I make a simple HTML page and load it as file://myhtmlfilelocation/myhtmlfile.html and try to make an ajax request"
The cause of your problem is that you are using the file:// URL scheme, instead of the http:// protocol scheme. You can find information about this scheme in Section 3.10 of RFC 1738. Here is an excerpt:
The file URL scheme is used to designate files accessible on a particular host computer. This scheme, unlike most other URL schemes, does not designate a resource that is universally accessible over the Internet.
You should be able to resolve your issue by using the http:// scheme instead of the file:// scheme when you make your asynchronous HTTP request.
I am looking for a way to wrap APIs around default functions in my PHP-based web applications, databases and CMSs.
I have looked around and found several "skeleton" frameworks. In addition to the answers in my question, there is Tonic, a REST framework I like because it is very lightweight.
I like REST the best for its simplicity, and would like to create an API architecture based on it. I'm trying to get my head around the basic principles and have not fully understood it yet. Therefore, a number of questions.
1. Am I understanding it right?
Say I have a resource "users". I could set up a number of URIs like so:
/api/users when called with GET, lists users
/api/users when called with POST, creates user record
/api/users/1 when called with GET, shows user record
when called with PUT, updates user record
when called with DELETE, deletes user record
is this a correct representation of a RESTful architecture so far?
2. I need more verbs
Create, Update and Delete may be enough in theory, but in practice I will have the need for a lot more verbs. I realize these are things that could be embedded in an update request, but they are specific actions that can have specific return codes and I wouldn't want to throw them all into one action.
Some that come to mind in the user example are:
activate_login
deactivate_login
change_password
add_credit
how would I express actions such as those in a RESTful URL architecture?
My instinct would be to do a GET call to a URL like
/api/users/1/activate_login
and expect a status code back.
That deviates from the idea of using HTTP verbs, though. What do you think?
3. How to return error messages and codes
A great part of REST's beauty stems from its use of standard HTTP methods. On an error, I emit a header with a 3xx,4xx or 5xx error status code. For a detailed error description, I can use the body (right?). So far so good. But what would be the way to transmit a proprietary error code that is more detailed in describing what went wrong (e.g. "failed to connect to database", or "database login wrong")? If I put it into the body along with the message, I have to parse it out afterwards. Is there a standard header for this kind of thing?
4. How to do authentication
What would a API key based authentication following REST principles look like?
Are there strong points against using sessions when authenticating a REST client, other than that it's a blatant violation of the REST principle? :) (only half kidding here, session based authentication would play well with my existing infrastructure.)
I noticed this question a couple of days late, but I feel that I can add some insight. I hope this can be helpful towards your RESTful venture.
Point 1: Am I understanding it right?
You understood right. That is a correct representation of a RESTful architecture. You may find the following matrix from Wikipedia very helpful in defining your nouns and verbs:
When dealing with a Collection URI like: http://example.com/resources/
GET: List the members of the collection, complete with their member URIs for further navigation. For example, list all the cars for sale.
PUT: Meaning defined as "replace the entire collection with another collection".
POST: Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation.
DELETE: Meaning defined as "delete the entire collection".
When dealing with a Member URI like: http://example.com/resources/7HOU57Y
GET: Retrieve a representation of the addressed member of the collection expressed in an appropriate MIME type.
PUT: Update the addressed member of the collection or create it with the specified ID.
POST: Treats the addressed member as a collection in its own right and creates a new subordinate of it.
DELETE: Delete the addressed member of the collection.
Point 2: I need more verbs
In general, when you think you need more verbs, it may actually mean that your resources need to be re-identified. Remember that in REST you are always acting on a resource, or on a collection of resources. What you choose as the resource is quite important for your API definition.
Activate/Deactivate Login: If you are creating a new session, then you may want to consider "the session" as the resource. To create a new session, use POST to http://example.com/sessions/ with the credentials in the body. To expire it use PUT or a DELETE (maybe depending on whether you intend to keep a session history) to http://example.com/sessions/SESSION_ID.
Change Password: This time the resource is "the user". You would need a PUT to http://example.com/users/USER_ID with the old and new passwords in the body. You are acting on "the user" resource, and a change password is simply an update request. It's quite similar to the UPDATE statement in a relational database.
My instinct would be to do a GET call
to a URL like
/api/users/1/activate_login
This goes against a very core REST principle: The correct usage of HTTP verbs. Any GET request should never leave any side effect.
For example, a GET request should never create a session on the database, return a cookie with a new Session ID, or leave any residue on the server. The GET verb is like the SELECT statement in a database engine. Remember that the response to any request with the GET verb should be cache-able when requested with the same parameters, just like when you request a static web page.
Point 3: How to return error messages and codes
Consider the 4xx or 5xx HTTP status codes as error categories. You can elaborate the error in the body.
Failed to Connect to Database: / Incorrect Database Login: In general you should use a 500 error for these types of errors. This is a server-side error. The client did nothing wrong. 500 errors are normally considered "retryable". i.e. the client can retry the same exact request, and expect it to succeed once the server's troubles are resolved. Specify the details in the body, so that the client will be able to provide some context to us humans.
The other category of errors would be the 4xx family, which in general indicate that the client did something wrong. In particular, this category of errors normally indicate to the client that there is no need to retry the request as it is, because it will continue to fail permanently. i.e. the client needs to change something before retrying this request. For example, "Resource not found" (HTTP 404) or "Malformed Request" (HTTP 400) errors would fall in this category.
Point 4: How to do authentication
As pointed out in point 1, instead of authenticating a user, you may want to think about creating a session. You will be returned a new "Session ID", along with the appropriate HTTP status code (200: Access Granted or 403: Access Denied).
You will then be asking your RESTful server: "Can you GET me the resource for this Session ID?".
There is no authenticated mode - REST is stateless: You create a session, you ask the server to give you resources using this Session ID as a parameter, and on logout you drop or expire the session.
Simply put, you are doing this completely backward.
You should not be approaching this from what URLs you should be using. The URLs will effectively come "for free" once you've decided upon what resources are necessary for your system AND how you will represent those resources, and the interactions between the resources and application state.
To quote Roy Fielding
A REST API should spend almost all of
its descriptive effort in defining the
media type(s) used for representing
resources and driving application
state, or in defining extended
relation names and/or
hypertext-enabled mark-up for existing
standard media types. Any effort spent
describing what methods to use on what
URIs of interest should be entirely
defined within the scope of the
processing rules for a media type
(and, in most cases, already defined
by existing media types). [Failure
here implies that out-of-band
information is driving interaction
instead of hypertext.]
Folks always start with the URIs and think this is the solution, and then they tend to miss a key concept in REST architecture, notably, as quoted above, "Failure here implies that out-of-band information is driving interaction instead of hypertext."
To be honest, many see a bunch of URIs and some GETs and PUTs and POSTs and think REST is easy. REST is not easy. RPC over HTTP is easy, moving blobs of data back and forth proxied through HTTP payloads is easy. REST, however, goes beyond that. REST is protocol agnostic. HTTP is just very popular and apt for REST systems.
REST lives in the media types, their definitions, and how the application drives the actions available to those resources via hypertext (links, effectively).
There are different view about media types in REST systems. Some favor application specific payloads, while others like uplifting existing media types in to roles that are appropriate for the application. For example, on the one hand you have specific XML schemas designed suited to your application versus using something like XHTML as your representation, perhaps through microformats and other mechanisms.
Both approaches have their place, I think, the XHTML working very well in scenarios that overlap both the human driven and machine driven web, whereas the former, more specific data types I feel better facilitate machine to machine interactions. I find the uplifting of commodity formats can make content negotiation potentially difficult. "application/xml+yourresource" is much more specific as a media type than "application/xhtml+xml", as the latter can apply to many payloads which may or may not be something a machine client is actually interested in, nor can it determine without introspection.
However, XHTML works very well (obviously) in the human web where web browsers and rendering is very important.
You application will guide you in those kinds of decisions.
Part of the process of designing a REST system is discovering the first class resources in your system, along with the derivative, support resources necessary to support the operations on the primary resources. Once the resources are discovered, then the representation of those resources, as well as the state diagrams showing resource flow via hypertext within the representations because the next challenge.
Recall that each representation of a resource, in a hypertext system, combines both the actual resource representation along with the state transitions available to the resource. Consider each resource a node in a graph, with the links being the lines leaving that node to other states. These links inform clients not only what can be done, but what is required for them to be done (as a good link combines the URI and the media type required).
For example, you may have:
<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
Your documentation will talk about the rel field named "users", and the media type of "application/xml+youruser".
These links may seem redundant, they're all talking to the same URI, pretty much. But they're not.
This is because for the "users" relation, that link is talking about the collection of users, and you can use the uniform interface to work with the collection (GET to retrieve all of them, DELETE to delete all of them, etc.)
If you POST to this URL, you will need to pass a "application/xml+usercollection" document, which will probably only contain a single user instance within the document so you can add the user, or not, perhaps, to add several at once. Perhaps your documentation will suggest that you can simply pass a single user type, instead of the collection.
You can see what the application requires in order to perform a search, as defined by the "search" link and it's mediatype. The documentation for the search media type will tell you how this behaves, and what to expect as results.
The takeaway here, though, is the URIs themselves are basically unimportant. The application is in control of the URIs, not the clients. Beyond a few 'entry points', your clients should rely on the URIs provided by the application for its work.
The client needs to know how to manipulate and interpret the media types, but doesn't much need to care where it goes.
These two links are semantically identical in a clients eyes:
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>
So, focus on your resources. Focus on their state transitions in the application and how that's best achieved.
re 1: This looks fine so far. Remember to return the URI of the newly created user in a "Location:" header as part of the response to POST, along with a "201 Created" status code.
re 2: Activation via GET is a bad idea, and including the verb in the URI is a design smell. You might want to consider returning a form on a GET. In a Web app, this would be an HTML form with a submit button; in the API use case, you might want to return a representation that contains a URI to PUT to to activate the account. Of course you can include this URI in the response on POST to /users, too. Using PUT will ensure your request is idempotent, i.e. it can safely be sent again if the client isn't sure about success. In general, think about what resources you can turn your verbs into (sort of "nounification of verbs"). Ask yourself what method your specific action is most closely aligned with. E.g. change_password -> PUT; deactivate -> probably DELETE; add_credit -> possibly POST or PUT. Point the client to the appropriate URIs by including them in your representations.
re 3. Don't invent new status codes, unless you believe they're so generic they merit being standardized globally. Try hard to use the most appropriate status code available (read about all of them in RFC 2616). Include additional information in the response body. If you really, really are sure you want to invent a new status code, think again; if you still believe so, make sure to at least pick the right category (1xx -> OK, 2xx -> informational, 3xx -> redirection; 4xx-> client error, 5xx -> server error). Did I mention that inventing new status codes is a bad idea?
re 4. If in any way possible, use the authentication framework built into HTTP. Check out the way Google does authentication in GData. In general, don't put API keys in your URIs. Try to avoid sessions to enhance scalability and support caching - if the response to a request differs because of something that has happened before, you've usually tied yourself to a specific server process instance. It's much better to turn session state into either client state (e.g. make it part of subsequent requests) or make it explicit by turning it into (server) resource state, i.e. give it its own URI.
1. You've got the right idea about how to design your resources, IMHO. I wouldn't change a thing.
2. Rather than trying to extend HTTP with more verbs, consider what your proposed verbs can be reduced to in terms of the basic HTTP methods and resources. For example, instead of an activate_login verb, you could set up resources like: /api/users/1/login/active which is a simple boolean. To activate a login, just PUT a document there that says 'true' or 1 or whatever. To deactivate, PUT a document there that is empty or says 0 or false.
Similarly, to change or set passwords, just do PUTs to /api/users/1/password.
Whenever you need to add something (like a credit) think in terms of POSTs. For example, you could do a POST to a resource like /api/users/1/credits with a body containing the number of credits to add. A PUT on the same resource could be used to overwrite the value rather than add. A POST with a negative number in the body would subtract, and so on.
3. I'd strongly advise against extending the basic HTTP status codes. If you can't find one that matches your situation exactly, pick the closest one and put the error details in the response body. Also, remember that HTTP headers are extensible; your application can define all the custom headers that you like. One application that I worked on, for example, could return a 404 Not Found under multiple circumstances. Rather than making the client parse the response body for the reason, we just added a new header, X-Status-Extended, which contained our proprietary status code extensions. So you might see a response like:
HTTP/1.1 404 Not Found
X-Status-Extended: 404.3 More Specific Error Here
That way a HTTP client like a web browser will still know what to do with the regular 404 code, and a more sophisticated HTTP client can choose to look at the X-Status-Extended header for more specific information.
4. For authentication, I recommend using HTTP authentication if you can. But IMHO there's nothing wrong with using cookie-based authentication if that's easier for you.
REST Basics
REST have an uniform interface constraint, which states that the REST client must rely on standards instead of application specific details of the actual REST service, so the REST client won't break by minor changes, and it will probably be reusable.
So there is a contract between the REST client and the REST service. If you use HTTP as the underlying protocol, then the following standards are part of the contract:
HTTP 1.1
method definitions
status code definitions
cache control headers
accept and content-type headers
auth headers
IRI (utf8 URI)
body (pick one)
registered application specific MIME type, e.g. maze+xml
vendor specific MIME type, e.g. vnd.github+json
generic MIME type with
application specific RDF vocab, e.g. ld+json & hydra, schema.org
application specific profile, e.g. hal+json & profile link param (I guess)
hyperlinks
what should contain them (pick one)
sending in link headers
sending in a hypermedia response, e.g. html, atom+xml, hal+json, ld+json&hydra, etc...
semantics
use IANA link relations and probably custom link relations
use an application specific RDF vocab
REST has a stateless constraint, which declares that the communication between the REST service and client must be stateless. This means that the REST service cannot maintain the client states, so you cannot have a server side session storage. You have to authenticate every single request. So for example HTTP basic auth (part of the HTTP standard) is okay, because it sends the username and password with every request.
To answer you questions
Yes, it can be.
Just to mention, the clients do not care about the IRI structure, they care about the semantics, because they follow links having link relations or linked data (RDF) attributes.
The only thing important about the IRIs, that a single IRI must identify only a single resource. It is allowed to a single resource, like an user, to have many different IRIs.
It is pretty simple why we use nice IRIs like /users/123/password; it is much easier to write the routing logic on the server when you understand the IRI simply by reading it.
You have more verbs, like PUT, PATCH, OPTIONS, and even more, but you don't need more of them... Instead of adding new verbs you have to learn how to add new resources.
deactivate_login -> PUT /login/active false
change_password -> PUT /user/xy/password "newpass"
add_credit -> POST /credit/raise {details: {}}
(The login does not make sense from REST perspective, because of the stateless constraint.)
Your users do not care about why the problem exist. They want to know only if there is success or error, and probably an error message which they can understand, for example: "Sorry, but we weren't able to save your post.", etc...
The HTTP status headers are your standard headers. Everything else should be in the body I think. A single header is not enough to describe for example detailed multilingual error messages.
The stateless constraint (along with the cache and layered system constraints) ensures that the service scales well. You surely don't wan't to maintain millions of sessions on the server, when you can do the same on the clients...
The 3rd party client gets an access token if the user grants access to it using the main client. After that the 3rd party client sends the access token with every request. There are more complicated solutions, for example you can sign every single request, etc. For further details check the OAuth manual.
Related literature
Architectural Styles and the Design of Network-based Software Architectures
Dissertation of Roy Thomas Fielding (author of REST)
2000, University of California, Irvine
Third Generation Web APIs - Bridging the Gap between REST and Linked Data
Dissertation of Markus Lanthaler (co-author of JSON-LD and author of Hydra)
2014, Graz University of Technology, Austria
For the examples you stated I'd use the following:
activate_login
POST /users/1/activation
deactivate_login
DELETE /users/1/activation
change_password
PUT /passwords (this assumes the user is authenticated)
add_credit
POST /credits (this assumes the user is authenticated)
For errors you'd return the error in the body in the format that you got the request in, so if you receive:
DELETE /users/1.xml
You'd send the response back in XML, the same would be true for JSON etc...
For authentication you should use http authentication.
Use post when you don't know how the new resource URI would look like (you create new user, application would assign the new user it's id), PUT for updating or creating resources that you know how are they going to be represented (example: PUT /myfiles/thisismynewfile.txt)
return the error description in message body
You can use HTTP authentication (if it's enough)
Web services should be stateles
I would suggest (as a first pass) that PUT should only be used for updating existing entities. POST should be used for creating new ones. i.e.
/api/users when called with PUT, creates user record
doesn't feel right to me. The rest of your first section (re. verb usage) looks logical, however.
Verbose, but copied from the HTTP 1.1 method specification at http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
9.3 GET
The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI. If the Request-URI refers to a data-producing process, it is the produced data which shall be returned as the entity in the response and not the source text of the process, unless that text happens to be the output of the process.
The semantics of the GET method change to a "conditional GET" if the request message includes an If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match, or If-Range header field. A conditional GET method requests that the entity be transferred only under the circumstances described by the conditional header field(s). The conditional GET method is intended to reduce unnecessary network usage by allowing cached entities to be refreshed without requiring multiple requests or transferring data already held by the client.
The semantics of the GET method change to a "partial GET" if the request message includes a Range header field. A partial GET requests that only part of the entity be transferred, as described in section 14.35. The partial GET method is intended to reduce unnecessary network usage by allowing partially-retrieved entities to be completed without transferring data already held by the client.
The response to a GET request is cacheable if and only if it meets the requirements for HTTP caching described in section 13.
See section 15.1.3 for security considerations when used for forms.
9.5 POST
The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line. POST is designed to allow a uniform method to cover the following functions:
- Annotation of existing resources;
- Posting a message to a bulletin board, newsgroup, mailing list,
or similar group of articles;
- Providing a block of data, such as the result of submitting a
form, to a data-handling process;
- Extending a database through an append operation.
The actual function performed by the POST method is determined by the server and is usually dependent on the Request-URI. The posted entity is subordinate to that URI in the same way that a file is subordinate to a directory containing it, a news article is subordinate to a newsgroup to which it is posted, or a record is subordinate to a database.
The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.
If a resource has been created on the origin server, the response SHOULD be 201 (Created) and contain an entity which describes the status of the request and refers to the new resource, and a Location header (see section 14.30).
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.
POST requests MUST obey the message transmission requirements set out in section 8.2.
See section 15.1.3 for security considerations.
9.6 PUT
The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI. If a new resource is created, the origin server MUST inform the user agent via the 201 (Created) response. If an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request. If the resource could not be created or modified with the Request-URI, an appropriate error response SHOULD be given that reflects the nature of the problem. The recipient of the entity MUST NOT ignore any Content-* (e.g. Content-Range) headers that it does not understand or implement and MUST return a 501 (Not Implemented) response in such cases.
If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.
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. If the server desires that the request be applied to a different URI,
it MUST send a 301 (Moved Permanently) response; the user agent MAY then make its own decision regarding whether or not to redirect the request.
A single resource MAY be identified by many different URIs. For example, an article might have a URI for identifying "the current version" which is separate from the URI identifying each particular version. In this case, a PUT request on a general URI might result in several other URIs being defined by the origin server.
HTTP/1.1 does not define how a PUT method affects the state of an origin server.
PUT requests MUST obey the message transmission requirements set out in section 8.2.
Unless otherwise specified for a particular entity-header, the entity-headers in the PUT request SHOULD be applied to the resource created or modified by the PUT.
9.7 DELETE
The DELETE method requests that the origin server delete the resource identified by the Request-URI. This method MAY be overridden by human intervention (or other means) on the origin server. The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully. However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location.
A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.
If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale. Responses to this method are not cacheable.
About REST return codes: it is wrong to mix HTTP protocol codes and REST results.
However, I saw many implementations mixing them, and many developers may not agree with me.
HTTP return codes are related to the HTTP Request itself. A REST call is done using a Hypertext Transfer Protocol request and it works at a lower level than invoked REST method itself. REST is a concept/approach, and its output is a business/logical result, while HTTP result code is a transport one.
For example, returning "404 Not found" when you call /users/ is confuse, because it may mean:
URI is wrong (HTTP)
No users are found (REST)
"403 Forbidden/Access Denied" may mean:
Special permission needed. Browsers can handle it by asking the user/password. (HTTP)
Wrong access permissions configured on the server. (HTTP)
You need to be authenticated (REST)
And the list may continue with '500 Server error" (an Apache/Nginx HTTP thrown error or a business constraint error in REST) or other HTTP errors etc...
From the code, it's hard to understand what was the failure reason, a HTTP (transport) failure or a REST (logical) failure.
If the HTTP request physically was performed successfully it should always return 200 code, regardless is the record(s) found or not. Because URI resource is found and was handled by the http server. Yes, it may return an empty set. Is it possible to receive an empty web-page with 200 as http result, right?
Instead of this you may return 200 HTTP code and simply a JSON with an empty array/object, or to use a bool result/success flag to inform about the performed operation status.
Also, some internet providers may intercept your requests and return you a 404 http code. This does not means that your data are not found, but it's something wrong at transport level.
From Wiki:
In July 2004, the UK telecom provider BT Group deployed the Cleanfeed
content blocking system, which returns a 404 error to any request for
content identified as potentially illegal by the Internet Watch
Foundation. Other ISPs return a HTTP 403 "forbidden" error in the same
circumstances. The practice of employing fake 404 errors as a means to
conceal censorship has also been reported in Thailand and Tunisia. In
Tunisia, where censorship was severe before the 2011 revolution,
people became aware of the nature of the fake 404 errors and created
an imaginary character named "Ammar 404" who represents "the invisible
censor".