How to have a root query/mutation argument(s) in GraphQL API? - graphql

I need to have a "global argument" that can be specified (at most) once and applies to the entire request (having however many queries/mutations inside). If I were able to have the client specify it in query(arg: "value") {...} and/or mutation(arg: "value") {...} I would... but I understand this is reserved for "variables". I dislike other options I am aware of:
HTTP header - ties this to HTTP only, not in schema, not documented nicely.
POST /graphql
X-MyArg: some-value
...
{"query":"{someQuery{id name}}"}
HTTP (URL) query string parameter - ugh... I like the single common URL, also same problems as with (1)
POST /graphql?myArg=some-value
...
{"query":"{someQuery{id name}}"}
Introduce an intermediate wrapper field to expose this argument ... but this makes everything longer and I don't know of a way saying "this must be specified/requested at most once", while supporting multiple occurrences makes no sense for at least some of these (e.g. authentication / authorization / security related and others).
POST /graphql
...
{"query":"{wrapper(arg: \"some-value\"){someQuery{id name}}}"}
Cheat/hack and require an $arg variable (meant to be defined by the API client(s)) to be specified while somehow preventing the framework I am using from throwing up when that variable isn't actually referenced from anywhere inside.
POST /graphql
...
{"query":"query($arg:String){someQuery{id name}}","variables":{"arg":"some-value"}}
Can anyone help? Am I missing something or am I really forced to pick one of those poison pills?

Related

What HTTP Protocol can I use if I need to GET something from the server but I also need to send a requestbody?

I am using SpringBoot...
I can not use GET protocol and include a body, but I am not going to create or update anything on the server so I do not want to use POST or PUT, any other protocol that acts like a GET with body?
if you wonder what I need to send in that body it is an url parameter, like for example http://somewebsite.com/stuff/etc and I feel that putting this inside a request body is better than putting it as a requestparam
I can not use GET protocol and include a body, but I am not going to create or update anything on the server so I do not want to use POST or PUT, any other protocol that acts like a GET with body?
Your best bet, where suitable, would be to mimic how HTML forms work; which is to say having a family of resources with identifiers that are filled in by the client (in general, via URI templates -- often via query parameters as would happen with an HTML form).
When that's not appropriate: as of 2022-11, your best bet is POST. It's not a great answer (in particular, general purpose HTTP components won't know that the semantics of the request are safe), but it is the best option available of the registered methods.
POST serves many useful purposes in HTTP, including the general purpose of "
"this action isn’t worth standardizing." -- Roy Fielding, 2009
Eventually, the HTTPbis-wg will finalize the safe-method-with-a-body proposal, and at that point that will become a much better option than POST (for the cases that match the new semantics).

Is it possible to return an error for an extra query parameter shows up in light-4j request

I have a question about the light-rest-4j URL validation, for example, if I have a POST request path /party, if I type the path as /party11, I will get error: No handler defined for path /party11, but if I put /party?qqqq, It will pass through, and system treat it as /party should we add validation for this? Our QA team creates this as a defect, in case user input it by mistake, they expect to have error message return.
The light-rest-4j framework validates the request/response based on the OpenAPI specification during the runtime; however, it only validates based on the spec — nothing more and nothing less. In most cases, the spec will define the type of headers, query parameters, path parameters, and cookies, as well as if they are required. We make sure these are validated as defined. For anything that is not defined in the spec, we are doing nothing. For example, an extra query parameter or an extra header in the request will be ignored as they are not defined in the spec. We cannot do any negative validation as we don't know if any client will add additional headers or query parameters for tracing, auditing, etc. A request that comes from one client might be different than another one comes from the same client through a gateway or proxy.

GCP API methods: empty request body vs {}?

Some GCP API methods require an empty request body, others require {} in the body. I can't figure out any pattern.
Examples of methods that require an empty request body, and return an error if called with {}:
https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/getIamPolicy
https://cloud.google.com/iam/reference/rest/v1/roles/list
Examples of methods that require {} in the body, and return an error if called with an empty body:
https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/getIamPolicy
https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/create
Confusingly, all four of these docs say that the request body must be empty! For the second group, I'd say that's a bug: the body must be non-empty; it must be {}.
This is pretty annoying - it feels like random difference peppered across the methods? Is there any rhyme or reason here? Couldn't the body {} methods accept an empty body?
Some ideas that don't seem to explain the difference:
Since many products use IAM, those functions could have quirky behavior. But see above - getIamPolicy is different between products.
Different product teams could decide on different local conventions. But see above - the pubsub API has calls in each camp.
The first two links that you shared are HTTP GET methods, which should not have a body, as it should only retrieve data, and all the information can be passed through the URL and some query parameters.
The other two links are HTTP PUT methods, which expect a payload to update the current content of a given entity.
You can find more explanation about how the HTTP methods are defined in the IETF RFC 2616, explaining the HTTP protocol.

Combining GET and POST in Sinatra (Ruby)

I am trying to make a RESTful api and have some function which needs credentials. For example say I'm writing a function which finds all nearby places within a certain radius, but only authorised users can use it.
One way to do it is to send it all using GET like so:
http://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30&username=john&password=blabla123
but obviously that's the worst possible way to do it.
Is it possible to instead move the username and password fields and embed them as POST variables over SSL, so the URL will only look like so:
https://myapi.heroku.com/getNearbyPlaces?lon=12.343523&lat=56.123533&radius=30
and the credentials will be sent encrypted.
How would I then in Sinatra and Ruby properly get at the GET and POST variables? Is this The Right Way To Do It? If not why not?
If you are really trying to create a restful API instead if some URL endpoints which happen to speak some HTTP dialect, you should stick to GET. It's even again in your path, so you seem to be pretty sure it's a get.
Instead of trying to hide the username and password in GET or POST parameters, you should instead use Basic authentication, which was invented especially for that purpose and is universally available in clients (and is available using convenience methods in Sinatra).
Also, if you are trying to use REST, you should embrace the concept of resources and resoiurce collections (which is implied by the R and E of REST). So you have a single URL like http://myapi.heroku.com/NearbyPlaces. If you GET there, you gather information about that resource, if you POST, you create a new resource, if you PUT yopu update n existing resource and if you DELETE, well, you delete it. What you should do before is th structure your object space into these resources and design your API around it.
Possibly, you could have a resource collection at http://myapi.heroku.com/places. Each place as a resource has a unique URL like http://myapi.heroku.com/places/123. New polaces can be created by POSTing to http://myapi.heroku.com/places. And nearby places could be gathered by GETing http://myapi.heroku.com/places/nearby?lon=12.343523&lat=56.123533&radius=30. hat call could return an Array or URLs to nearby places, e.g.
[
"http://myapi.heroku.com/places/123",
"http://myapi.heroku.com/places/17",
"http://myapi.heroku.com/places/42"
]
If you want to be truly discoverable, you might also embrace HATEOAS which constraints REST smentics in a way to allows API clients to "browse" through the API as a user with a browser would do. To allow this, you use Hyperlink inside your API which point to other resources, kind of like in the example above.
The params that are part of the url (namely lon, lat and radius) are known as query parameters, the user and password information that you want to send in your form are known as form parameters. In Sinatra both of these type of parameters are made available in the params hash of a controller.
So in Sinatra you would be able to access your lon parameter as params[:lon] and the user parameter as params[:user].
I suggest using basic or digest authentication and a plain GET request. In other words, your request should be "GET /places?lat=x&lon=x&radius=x" and you should let HTTP handle the authentication. If I understand your situation correctly, this is the ideal approach and will certainly be the most RESTful solution.
As an aside, your URI could be improved. Having verbs ("get") and query-like adjectives ("nearby") in your resource names is not really appropriate. In general, resources should be nouns (ie. "places", "person", "books"). See the example request I wrote above; "get" is redundant because you are using a GET request and "nearby" is redundant because you are already querying by location.

GET vs POST in AJAX?

Why are there GET and POST requests in AJAX as it does not affect page URL anyway? What difference does it make by passing sensitive data over GET in AJAX as the data is not getting reflected to page URL?
You should use the proper HTTP verb according to what you require from your web service.
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.
Source: Wikipedia
Well, as for GET, you still have the url length limitation. Other than that, it is quite conceivable that the server treats POST and GET requests differently; thus the need to be able to specify what request you're doing.
Another difference between GET and POST is the way caching is handled in browsers. POST response is never cached. GET may or may not be cached based on the caching rules specified in your response headers.
Two primary reasons for having them:
GET requests have some pretty restrictive limitations on size; POST are typically capable of containing much more information.
The backend may be expecting GET or POST, depending on how it's designed. We need the flexibility of doing a GET if the backend expects one, or a POST if that's what it's expecting.
It's simply down to respecting the rules of the http protocol.
Get - calls must be idempotent. This means that if you call it multiple times you will get the same result. It is not intended to change the underlying data. You might use this for a search box etc.
Post - calls are NOT idempotent. It is allowed to make a change to the underlying data, so might be used in a create method. If you call it multiple times you will create multiple entries.
You normally send parameters to the AJAX script, it returns data based on these parameters. It works just like a form that has method="get" or method="post". When using the GET method, the parameters are passed in the query string. When using POST method, the parameters are sent in the post body.
Generally, if your parameters have very few characters and do not contain sensitive information then you send them via GET method. Sensitive data (e.g. password) or long text (e.g. an 8000 character long bio of a person) are better sent via POST method.
Thanks..
I mainly use the GET method with Ajax and I haven't got any problems until now except the following:
Internet Explorer (unlike Firefox and Google Chrome) cache GET calling if using the same GET values.
So, using some interval with Ajax GET can show the same results unless you change URL with irrelevant random number usage for each Ajax GET.
Others have covered the main points (context/idempotency, and size), but i'll add another: encryption. If you are using SSL and want to encrypt your input args, you need to use POST.
When we use the GET method in Ajax, only the content of the value of the field is sent, not the format in which the content is. For example, content in the text area is just added in the URL in case of the GET method (without a new line character). That is not the case in the POST method.

Resources