Android,Retrofit how to use #Headers? - retrofit

Currently, I am using Retrofit in Android.
Every REST call have different headers. I find there is key word #Header in retrofit in Retrofit, the example is as follows:
#GET("/tasks")
Call<List<Task>> getTasks(#Header("Content-Range") String contentRange);
But I also find another key words #Headers, How can I use Headers in Retrofit, because I have many headers, so I think #Headers maybe better.
Don't post okHttpClient method, I have already known how to use that.
Thanks

#Headers is for static headers, arguments cannot go there.
#Headers({
"X-Something: Foo",
"X-Else: Bar",
"Cache-Control: max-age=300000"
})
#GET("/getStuff") <Task> getStuff();
if you got many different headers per call then you need to use #Header or rethink your API on a backend. Alternatively you may add headers using Interceptor but I do not think this is the way to go.

Related

using different request parser depending on the queried route

I'm Implementing a mini http server using boost beast. the server has two different routes POST /upload/... and the other one is POST /info. The first one is used for uploading some big files and the other one is for hadling json objects. To keep the performance as hight as possible am I trying to parse each route with the suitable parser file_body and string_body/dynamic_body.
I was hoping that it is possible to do something like:
http::async_read_header(
socket_,
buffer_,
request_,
[self](beast::error_code ec, std::size_t)
{
if (!ec)
self->request_.body().data();
});
but it seems not possible.
Is there any way to use different request bodies depending on header info?
Many thanks in advance
This should be covered in the docs but here's how to do it: Use the type beast::request_parser<beast::empty_body> to first read the header, and then depending on the contents of the header you move-construct a new parser from the old one with the body type you want. Example:
// Deferred body type commitment
request_parser<empty_body> req0;
...
request_parser<string_body> req{std::move(req0)};
You can read the complete documentation on switching body types here:
https://www.boost.org/doc/libs/1_69_0/libs/beast/doc/html/beast/ref/boost__beast__http__parser/parser/overload5.html

Add Multiple WWW-Authenticate headers with OWIN

I want our service to advertise more than one authentication scheme: for example both Bearer and some custom scheme, say X-Custom. (I have an OWIN middleware component for each scheme). I take if from RFC 2616, sec 14.47 there is more than one way to do it:
Option a) multiple headers
WWW-Authenticate: Bearer
WWW-Authenticate: X-Custom
Option b) comma-separated list
WWW-Authenticate: Bearer, X-Custom
My preference would be option a) so a client only has to do something like Response.Headers.Exists("WWW-Authenticate", preferredScheme) instead of comma parsing the header (which the RFC says they should, but...)
However, Katana uses a dictionary for headers. Trying to add the second header throws an exception with "The key 'WWW-Authenticate' is already present in the dictionary."
Is there a way for a middleware component to inject more than one WWW-Authenticate header?
It is IDictionary<string, string[]>. Key is a string but value is an array of string. So, you just need to set the header like this.
app.Run(async (IOwinContext context) =>
{
context.Response.Headers.Add("WWW-Authenticate",
new[] { "Bearer", "X-Custom" });
// Some other code
});
UPDATE
I believe you are very kind to accept my answer as answer :). Thanks but not sure it answered your question and hence the edit. First of all, I did not get the point you tried to make, which is to add the different headers from different middleware and yet wanting to see them in different lines in the response. I do not think there is anyway to do this for standard HTTP headers like WWW-Authenticate. In fact, before I answered your question, I quickly wrote a small program to verify but the mistake I made was to misspell this header.
Because of that, I was actually getting the header values like this.
WWW-Authentciate: X-Custom
WWW-Authentciate: Bearer
Anyways, the following works in getting the header values in two lines.
app.Use(async (IOwinContext context, Func<Task> next) =>
{
context.Response.Headers.Set("WWW-Authenticate", "Bearer");
await next.Invoke();
});
app.Run(async (IOwinContext context) =>
{
var x = context.Response.Headers.Get("WWW-Authenticate");
context.Response.Headers.Remove("WWW-Authenticate");
context.Response.Headers.Add("WWW-Authenticate", new[] { "X-Custom", x });
});
However, this does not work for standard headers. Nonetheless, this is an interesting exercise but at the end of the day, there is no accepted standard in terms of the API here (as far as I know). Even if you somehow get this working the way you want, the moment you change an underlying OWIN component, say the server or host, you could get different behavior. After all, option a and option b are exactly the same and you should not see any difference if you are working on top of some library to read the headers, unless you do some low-level stuff.

Are PUT and POST requests required/expected to have a request body?

I'm writting a RESTful api, and at I'm thinking about the process of a user creating a key. I have the following possibilities:
GET request to /new/<keyname> - although it's very easy I think I won't use this, because I heard GET is for retrieving and/or listing information;
POST request to /<keyname> - This seemed to me easy and simple enough, but does not pass any data in the request body. Can I do it this way ? Is this weird ?
POST request to /keys passing in the request body "keyname=SomeKey" - Is this the correct way ?
I looked at this API from joyent and in all their PUT and POST requests they pass some data in the request body. Is this expected ? Is it really wrong not to require a request body in a PUT and POST request ?
I asked this question on the Http-WG. This was the most precise answer I got http://lists.w3.org/Archives/Public/ietf-http-wg/2010JulSep/0276.html
In summary, POST does not require a body. I would expect the same justification can be applied to PUT.
RFC2616 is the base RFC for HTTP 1.1
In the most general form, an HTTP message is this (note the optional body):
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line
Reading further gives this:
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. ...
and
9.6 PUT
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. ...
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.
Both POST and PUT include the phrase entity enclosed in the request.
Based on my reading, I believe that a body is desired (a non-normative description, I know) for both POST and PUT.
In the context of REST, POST is create and PUT is update. I can imagine creating an empty object (perhaps a placeholder for future information), but I don't imagine much use of an empty update.
It is not required. You can send a POST/PUT request without a body and instead use query string parameters. But be careful if your parameters contain characters that are not HTTP valid you will have to encode them.
For example if you need to POST 'hello world' to and end point you would have to make it look like this: http://api.com?param=hello%20world
Probably the best way is your third option: POST to /keys with keyname=SomeKey.
Here's why: You may wish to add another function to your API, for example create_new_user. It would then be difficult to tell the difference between a user trying to POST a key called create_new_user and a user trying to use the create_new_user function.
You are correct in saying that you should not be using GET to do this operation as the GET operation "SHOULD NOT have the significance of taking an action
other than retrieval." (RFC 2616).
To answer your question in one line. Yes it is expected to have Body/Content in body, but it is not required(Mandatory).
According to okHttp3 (an HTTP library for android): the following methods need a body: POST, PUT, PATCH, PROPPATCH (WebDAV) and REPORT (source). It even crashes if you try to do a request with the given methods without a body.

How should I implement a COUNT verb in my RESTful web service?

I've written a RESTful web service that supports the standard CRUD operations, and that can return a set of objects matching certain criteria (a SEARCH verb), but I'd like to add a higher-order COUNT verb, so clients can count the resources matching search criteria without having to fetch all of them.
A few options that occur to me:
Ignoring the HTTP specification and returning the object count in the response body of a HEAD request.
Duplicating the SEARCH verb's logic, but making a HEAD request instead of a GET request. The server then would encode the object count in a response header.
Defining a new HTTP method, COUNT, that returns the object count in the response body.
I'd prefer the API of the first approach, but I have to strike that option because it's non-compliant. The second approach seems most semantically correct, but the API isn't very convenient: clients will have to deal with response headers, when most of the time they want to be able to do something easy like response.count. So I'm leaning toward the third approach, but I'm concerned about the potential problems involved with defining a new HTTP method.
What would you do?
The main purpose of rest is to define a set of resources that you interact with using well defined verbs. You must thus avoid to define your own verbs. The number of resources should be considered as a different resource, with its own uri that you can simply GET.
For example:
GET resources?crit1=val1&crit2=val2
returns the list of resources and
GET resources/count?crit1=val1&crit2=val2
Another option is to use the conneg: e.g. Accept: text/uri-list returns the resources list and Accept: text/plain returns only the count
You can use HEAD without breaking the HTTP specification and you can indicate the count by using an HTTP Range header in the response:
HEAD /resource/?search=lorem
Response from the service, assuming that you return the first 20 results by default:
...
Content-Range: resources 0-20/12345
...
This way you transfer the amount of resources to the client within the header of the response message without the need to return a message body.
Update:
The solution suggested Yannick Loiseau will work fine. Just wanted to provide one other alternative approach which can be used to achieve what you need without the need to define a new resource of verb.
You can use GET and add the count into the body of the message. Then, if you API allows clients to request a range of results, you can use that in order to limit the size of message body to a minimum (since you only want the count). One way to do that would be to request an empty range (from 0 to 0), for example:
GET /resource/?search=lorem&range=0,0
The service could then respond as follows, indicating that there are 1234 matching resources in the result set:
<?xml version="1.0" encoding="UTF-8" ?>
<resources range="0-0/1234" />
Ignoring the HTTP specification and returning the object count in the response body of a HEAD request.
IMHO, this is a very bad idea. It may not work simply because you might have intermediaries that don't ignore the HTTP spec.
Defining a new HTTP method, COUNT, that returns the object count in the response body.
There is no problem with this approach. HTTP is extendable and you can define your own verbs. Some firewalls prohibit this, but they are usually also prohibit POST and DELETE and X-HTTP-Method-Override header is widely supported.
Another option, to add a query param to your url, something like: ?countOnly=true

Is it considered bad practice to perform HTTP POST without entity body?

I need to invoke a process which doesn't require any input from the user, just a trigger. I plan to use POST /uri without a body to trigger the process. I want to know if this is considered bad from both HTTP and REST perspectives?
I asked this question on the IETF HTTP working group a few months ago. The short answer is: NO, it's not a bad practice (but I suggest reading the thread for more details).
Using a POST instead of a GET is perfectly reasonable, since it also instructs the server (and gateways along the way) not to return a cached response.
POST is completely OK. In difference of GET with POST you are changing the state of the system (most likely your trigger is "doing" something and changing data).
I used POST already without payload and it "feels" OK. One thing you should do when using POST without payload: Pass header Content-Length: 0. I remember problems with some proxies when I api-client didn't pass it.
If you use POST /uri without a body it is something like using a function which does not take an argument .e.g int post (void); so it is reasonable to have function to your resource class which can change the state of an object without having an argument. If you consider to implement the Unix touch function for a URI, is not it be good choice?
Yes, it's OK to send a POST request without a body and instead use query string parameters. But be careful if your parameters contain characters that are not HTTP valid you will have to encode them.
For example if you need to POST 'hello world' to and end point you would have to make it look like this: http://api.com?param=hello%20world
Support for the answers that POST is OK in this case is that in Python's case, the OpenAPI framework "FastAPI" generates a Swagger GUI (see image) that doesn't contain a Body section when a method (see example below) doesn't have a parameter to accept a body.
the method "post_disable_db" just accepts a path parameter "db_name" and doesn't have a 2nd parameter which would imply a mandatory body.
#router.post('/{db_name}/disable',
status_code=HTTP_200_OK,
response_model=ResponseSuccess,
summary='',
description=''
)
async def post_disable_db(db_name: str):
try:
response: ResponseSuccess = Handlers.databases_handler.post_change_db_enabled_state(db_name, False)
except HTTPException as e:
raise (e)
except Exception as e:
logger.exception(f'Changing state of DB to enabled=False failed due to: {e.__repr__()}')
raise HTTPException(HTTP_500_INTERNAL_SERVER_ERROR, detail=e.__repr__())
return response

Resources