In this post, we will see the different REST API components w.r.t standards and design aspects
Query parameters and QueryString length in HTTP GET
Although officially there is no limit specified by RFC 2616, many security protocols and recommendations state that maxQueryStrings on a server should be set to a maximum character limit of 1024. While the entire URL, including the querystring, should be set to a max of 2048 characters. This is to prevent the Slow HTTP Request DDOS vulnerability on a web server. This typically shows up as a vulnerability on the Qualys Web Application Scanner and other security scanners.
Please see the below example code for Windows IIS Servers with Web.config:
<system.webServer> <security> <requestFiltering> <requestLimits maxQueryString="1024" maxUrl="2048"> <headerLimits> <add header="Content-type" sizeLimit="100" /> </headerLimits> </requestLimits> </requestFiltering> </security> </system.webServer>
This would also work on a server level using machine.config.
Note: Limiting query string and URL length may not completely prevent Slow HTTP Requests DDOS attack but it is one step you can take to prevent it.
414 URI Too Long (RFC 7231):
The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request, in which case it should be converted to a POST request. Called “Request-URI Too Long” previously.
- Microsoft Internet Explorer (Browser)
Microsoft states that the maximum length of a URL in Internet Explorer is 2,083 characters, with no more than 2,048 characters in the path portion of the URL. Attempts to use URLs longer than this produced a clear error message in Internet Explorer.
- Microsoft Edge (Browser)
The limit appears to be around 81578 characters.
It stops displayingthe URL after 64k characters, but can serve more than 100k characters. No further testing was done beyond that.
- Firefox (Browser)
After 65,536 characters, the location bar no longer displays the URL in Windows Firefox 1.5.x. However, longer URLs will work. No further testing was done after 100,000 characters.
- Safari (Browser)
At least 80,000 characters will work. Testing was not tried beyond that.
- Opera (Browser)
At least 190,000 characters will work. Stopped testing after 190,000 characters. Opera 9 for Windows continued to display a fully editable, copyable and pasteable URL in the location bar even at 190,000 characters.
- Apache (Server)
Early attempts to measure the maximum URL length in web browsers bumped into a server URL length limit of approximately 4,000 characters, after which Apache produces a “413 Entity Too Large” error. The current up to date Apache build found in Red Hat Enterprise Linux 4 was used. The official Apache documentation only mentions an 8,192-byte limit on an individual field in a request.
- Microsoft Internet Information Server (Server)
The default limit is 16,384 characters (yes, Microsoft’s web server accepts longer URLs than Microsoft’s web browser). This is configurable.
- Perl HTTP::Daemon (Server)
Up to 8,000 bytes will work. Those constructing web application servers with Perl’s HTTP::Daemon module will encounter a 16,384 byte limit on the combined size of all HTTP request headers. This does not include POST-method form data, file uploads, etc., but it does include the URL. In practice this resulted in a 413 error when a URL was significantly longer than 8,000 characters. This limitation can be easily removed. Look for all occurrences of 16×1024 in Daemon.pm and replace them with a larger value. Of course, this does increase your exposure to denial of service attacks.
When to use @QueryParam versus @PathParam
REST may not be a standard as such, Most APIs tend to only have resource names and resource IDs in the path. Such as:
Some REST APIs use query strings for filtering, pagination and sorting, but REST isn’t a strict standard.
Recommendation is put any required parameters in the path, and any optional parameters should certainly be query string parameters. Putting optional parameters in the path will end up getting really messy when trying to write URL handlers that match different combinations.
When to use Headers versus URL parameters (PathParam or QueryParam)
GET /orders/view (custom HTTP header) CLIENT_ID: 23
GET /orders/view/client_id/23 or GET /orders/view/?client_id=23
The URL indicates the resource itself. A “client” is a resource that can be acted upon, so should be part of the base url: /orders/view/client/23.
Parameters are just that, to parameterize access to the resource. This especially comes into play with posts and searches: /orders/find?q=blahblah&sort=foo. There’s a fine line between parameters and sub-resources: /orders/view/client/23/active versus /orders/view/client/23?show=active. Recommendation is the sub-resource style and reserve parameters for searches.
Since each endpoint Represents a State Transfer (to mangle the mnemonic), custom headers should only be used for things that don’t involve the name of the resource (the url), the state of the resource (the body), or parameters directly affecting the resource (parameters). That leaves true metadata about the request for custom headers.
HTTP has a very wide selection of headers that cover most everything you’ll need. Where we could see custom headers which come up in a system to system request operating on behalf of a user. The proxy system will validate the user and add “X-User: userid” to the headers and use the system credentials to hit the endpoint. The receiving system validates that the system credentials are authorized to act on behalf of the user, then validate that the user is authorized to perform the action.
Custom headers have the following advantages:
- Can be read easily by network tools/scripts (authentication, meta info)
- Keeps urls free from security stuff (safer, not in browser/proxy caches)
- Keeps urls cleaner: allows for better caching of resources