2

i have a rest API that is a front end to a more complex SOAP based service. The soap based service uses extended(custom) WSA-addressing headers in order to perform its routing. The extension of the WSA-Addressing adds two header parameters country and city for example. Since the routing elements are mandatory I need to pass them in some form to the REST API and then use them on the SOAP client in order to get the routing right. I have two options with regards of the REST API:

  1. Pass them as HTTP headers
  2. Pass them as path parameters. Lets say that for example the two routing parameters are land and city and my REST resource ID is 123456.

them my GET will look like:

getResource/country/city/123456

If I use headers then it will be:

getResourfce/123456

It should be noted that the ID alone is uniquly identifying a resource , so the country and city are for routing only.

If I was using SOAP there would have been no question that I will use HEADERs. What is the situation when REST is used with regards of routing.

What is the proper way of expressing this parameters ? Headers or path elements ?

  • 2
    Using the REST paradigm you access resources. The path to the resource is typically $collection/$specific?$filter, e.g. /products/shoes?brand=Nike. – Thomas Junk Dec 10 '19 at 20:17
  • @ThomasJunk thanks for the answer. But I have read that the requestParameters should be optional and not mandatory. In my case though country and city are mandatory. Is this not changing the things ? – Alexandar Petrov Dec 10 '19 at 20:23
  • There's nothing wrong with required query string parameters. If the consumer doesn't pass them then you return a 400 indicating that country and city are required. – Dan Wilson Dec 10 '19 at 20:29
  • @DanWilson is using headers bad idea ? If yes why ? – Alexandar Petrov Dec 10 '19 at 20:31
  • @DanWilson why not path parameters? – Alexandar Petrov Dec 10 '19 at 20:33
1

It should be noted that the ID alone is uniquly identifying a resource , so the country and city are for routing only.

Sounds like the ID alone doesn't actually uniquely identify the resource, since if the underlying SOAP service requires them to find the resource and only having the ID can't identify the resource, they are in fact required to identify the resource.

Having IDs that are not shared across resources is not the same thing as the ID itself being able to uniquely identify a resource.

Even if /Canada/Toronto/12345 and /Ireland/Dublin/12345 will never happen because the IDs are not shared you still need this country and city information to get the correct resource.

So I would put them in the URL.

Don't put them in the header. This information has nothing to do with the HTTP transport level.

  • I think you are right. – Alexandar Petrov Dec 12 '19 at 19:05
  • "Don't put them in the header. This information has nothing to do with the HTTP transport level." this is a non-sequitur. – JimmyJames Dec 13 '19 at 22:00
  • Just because you can do something doesn't mean you should. The HTTP header is concerned with facilitating the state transfer of the resource, it doesn't and shouldn't care about specific business logic of the resource (ie the different states of the specific resource). – Cormac Mulhall Dec 17 '19 at 16:53
  • Note that in HTTP, some headers are used to communicate redirection and forwarding. It's not totally out of place what the OP is asking. It's just a little bit forced because it implies something else. A router, not a mere http server. – Laiv Dec 28 '19 at 15:18
  • That is quite different to using the header to construct the URI though, particularly when the construction in the header itself is resource specific (ie only done for certain types of resources) – Cormac Mulhall Dec 30 '19 at 9:32
1

Ultimately it's up to you to decide, both options are possible.

At first I didn't like the header approach but then I found two examples of header usage in RESTful services that make it look sensible:

  • Authorization: headers are used to control access rights to resources, including possibly different visibility of fields.
  • Accept: headers can be used to select the presentation of resources, i.e. the same resource could be presented as JSON, XML, or HTML data.

However, if each resource is only accessible with one specific country/city combination and the client needs to know that usa/new_york is needed for 11112222 but spain/madrid for 11112233, these should go into the path. Header values are not part of a URI, and remembering or finding out which country and city need to be passed in the request for a specific resource should not be the client's responsibility.

  • In my case one ID althought completly unique can exist only in one combination Of city, country. – Alexandar Petrov Dec 11 '19 at 6:51
  • What if partitioning change tomorrow to country Brand f.ex. Isnt IT a bit risky to build your uri around partitioning which may not exist tomorrow. Probably IT is pretty fixed but still. – Alexandar Petrov Dec 11 '19 at 7:34
  • Whether you put partitioning info into header or path doesn't matter in that situation. The client will have a non-working link. If you put routing in the path, you could handle this with a HTTP 301 response. How would you handle outdated header values? – Hans-Martin Mosner Dec 11 '19 at 7:58
-1

There is absolutely noting wrong about passing parameters in headers. Any decent REST framework will support it. It's not typically a first choice but there is one situation where you definitely should pass your parameters in headers:

RESTful web services should be careful to prevent leaking credentials. Passwords, security tokens, and API keys should not appear in the URL, as this can be captured in web server logs, which makes them intrinsically valuable.

  • In POST/PUT requests sensitive data should be transferred in the request body or request headers.
  • In GET requests sensitive data should be transferred in an HTTP Header.

While the above refers directly to security data, the same logic would apply to any other kind of sensitive information e.g. credit card numbers.

  • Authentication is different to resource specific content information. The HTTP header deals with facilitating the state transfer of resources. It doesn't care what type of resource. The resource itself (either the body or its URI) is concerned with the specifics of the resource. So this is really apples and oranges. Putting resource content type logic in the HTTP header is a REST anti-pattern and will make your API brittle and confusing to clients – Cormac Mulhall Dec 17 '19 at 17:00
  • @CormacMulhall Feel free to ignore the OWASP recommendations at your own peril. – JimmyJames Dec 17 '19 at 17:12
  • @CormacMulhall Wait, are you saying you don't use Accept and Content headers? That's bonkers. – JimmyJames Dec 17 '19 at 17:13
  • No, I'm saying Accept and Content headers don't care about the specific of the resource being transferred, they just take a Content Type which can be any string. It is up to the client and server to figure out the specific of that content type, not the HTTP protocol. Changing the Header based on the specific content type of the resource you are transferring state for is a recipe for long term problems maintaining your API and is a REST anti-pattern since the point of REST is that the HTTP protocol doesn't care about the specifics of the resource – Cormac Mulhall Dec 17 '19 at 17:32
  • @CormacMulhall I really don't know what that has to do with the subject here. If you are passing sensitive parameters, the security recommendation is that they not be in the URI. If you have content in the request, you can opt to put the sensitive parameter there. If you are doing a GET, you don't really have that option. I personally dislike the idea of turning a GET into a POST or PUT but some opt for that instead of using the headers. BTW custom headers are absolutely fine: developer.mozilla.org/en-US/docs/Web/HTTP/Headers – JimmyJames Dec 17 '19 at 17:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.