Which `format` would be negotiated for REST request? - django

There are three variants of format selection:
curl -uadmin:admin "http://localhost:8080/alfresco/service/hellouser.json"
curl -uadmin:admin "http://localhost:8080/alfresco/service/hellouser?format=json"
curl -uadmin:admin -H "Accept: text/html" "http://localhost:8080/alfresco/service/hellouser"
But this is unclear from the DOC what format would be selected for next query:
curl -uadmin:admin -H "Accept: text/html" "http://localhost:8080/alfresco/service/hellouser.xml?format=json"
I expect json here.
May someone provide links to relevant specifications or documentation which describes priority how {format} negotiated? like this is described for Rails:
Rails picks up the expected format from the query parameter format, or if not there from the URL path suffix, or it not there from the Accept header
UPD
The controller can handle all supplied formats: json, xml, html
UPD
Another corner case:
curl -uadmin:admin "http://localhost:8080/alfresco/service/hellouser.pl?format=json"
curl -uadmin:admin "http://localhost:8080/alfresco/service/hellouser.pl?format=xml"

I'd believe you wouldn't have a 200 response, only an error with content negotiation.
The code shows that:
?format=json(format_query_param) will be discarded by the .xml (format_suffix)
filter available renderers leaving only the XMLRenderer left
then it will loop on the accept header but none will match text/html
finally this will be down to the exception

Related

Why is the list of spaces of my Confluence wiki empty?

I have a Confluence wiki with over 1000 spaces. I try to retrieve the list of spaces of my Confluence wiki using the curl query:
curl -D -u user:password -X GET \
-H "Content-Type: application/json" https://[hostname]/rest/api/space
It returns an empty list of spaces:
{"results":[],"start":0,"limit":25,"size":0,
"_links":{"self":https://[hostname]/rest/api/space,
"e":https://[hostname],"context":""}}
What could be the issue?
https://developer.atlassian.com/cloud/confluence/rest/api-group-space/#api-wiki-rest-api-space-get states:
Note, the returned list will only contain spaces that the current user has permission to view.
That was indeed a permission issue: the account used to make the curl query had no permission for any spaces.

swagger auto-generated flask server headers

I'm using swagger editor (version 2.10.5) to generate a flask api that uses custom headers and started to add the following line to each path:
parameters:
- $ref: '#/parameters/X-Forwarded-Host'
the relative definition:
X-Forwarded-Host:
name: 'X-Forwarded-Host'
in: header
description: Forwarded host header
required: true
type: string
Then running the auto-generated flask server
$ python3 -m swagger_server
creates some problems:
When making a curl request, headers are not right evaluated:
$ curl -X GET --header 'Accept: application/json' --header 'X-Forwarded-Host: example.com' http://localhost:8080
returns
health_get() missing required positional argument: 'X_Forwarded_Host'
Auto-generated tests are useless too:
headers = [('X_Forwarded_Host', 'X_Forwarded_Host_example'), ...
What am I doing wrong? Why is swagger-editor (or codegen) setting all "-" to "_"?
Thanks in advance
Ok, I figured out..
The problem was NOT with swagger-editor itself but how it generates the flask (Connexion) code.
Connexion request handling docs (url) says:
"Currently, header parameters are not passed to the handler functions as parameters. But they can be accessed through the underlying connexion.request.headers object which aliases the flask.request.headers object."
The solution is to remove all function attributes (related to headers) from the auto-generated controller and pick them from the request object, therefore:
From:
def health_get(X_Forwarded_Host):
...
To:
def health_get():
forwarded_host = connexion.request.headers['X-Forwarded-Host']
Bye!

curl request through c++ for indexing solr document

I have used following code for indexing document in solr
CURL *curl = curl_easy_init();
CURLcode res;
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.0.164:8983/solr/collection1/update?replacefields=false -H 'Content-type: application/json' -d '[{\"id\":\"4000\", \"to\":\"Life is to.\", \"cc\":\"unknown \", \"subject\":\"Life\"}]'");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
if(CURLE_OK == res){
logger.LogError("res value CURLE_OK");
}
/* always cleanup */
curl_easy_cleanup(curl);
}
and the return value of curl_easy_perform(curl) i.e. res is CURLE_OK but the record is not indexing in collection1 of solr and while posting following command from terminal record is getting indexed
curl http://192.168.0.164:8983/solr/collection1/update?replacefields=false -H 'Content-type: application/json' -d '[{"id":"4000", "to":"Life is to.", "cc":"unknown ", "subject":"Life"}]'
You're not supplying cURL with your proper URL. Everything after the actual URL, -H 'Content-type: application/json' -d '[{\"id\":\"4000\", \"to\":\"Life is to.\", \"cc\":\"unknown \", \"subject\":\"Life\"}]', is just arguments to the cURL command line tool, and is not part of the URL.
The URL option should be only http://192.168.0.164:8983/solr/collection1/update?replacefields=false. The rest of the parameters has to be set as their own curl_easy_setopt calls.
To set the data to POST, use CURLOPT_POSTFIELDS.
Pass a char * as parameter, pointing to the full data to send in a HTTP POST operation. You must make sure that the data is formatted the way you want the server to receive it.
To set the proper request content type, use CURLOPT_HTTPHEADER.
Pass a pointer to a linked list of HTTP headers to pass to the server and/or proxy in your HTTP request. The same list can be used for both host and proxy requests!
After setting all the options call curl_easy_perform. You may also want to watch the log on the Solr server to see if Solr generates an exception. You can also set CURLOPT_ERRORBUFFER and CURLOPT_VERBOSE to get more information about any failure internally in cURL (CURLE_OK will be returned as long as cURL is able to make the request - but does not change if the server returns 400 or 404 or any actual error code on the server side (except if CURLOPT_FAILONERROR is set).

posting a parameter with integer value using requests lib

I have a curl command that was given to me that I have to convert using requests.
curl --request POST "https://www.example.com" --data "user_id=200" --data "user_data=je93jfe92dj220,39fjid20djd93f302,93jfieheio02hfne,902jfoienfieshiu202" --header "Authorization: Bearer [TOKEN]"
using requests, the call should be
hdr = {'Content-Type': 'Content-type: application/json',
'Authorization': 'Bearer TOKEN' }
payload = {"user_id":200,"records":"je93jfe92dj220,39fjid20djd93f302,93jfieheio02hfne,902jfoienfieshiu202"
requests.post('https://www.example.com', headers=hdr, data=json.dumps(payload))
This isn't working as I'm getting an error returned that the 'user_id' param must be an integer. Not sure how to ensure that, as aren't all parameters formatted as strings when sent? The curl command does work, however.
Im not really sure the reason, but to make this work, just change data=json.dumps(payload) to json=json.dumps(payload). This worked just fine for me.

Using "Content-Type:application/json" to post in curl gives HTTP/1.1 400 BAD REQUEST

When I make a post request using the following
curl -i -d "username=rock&password=rock" http://my_VM_IP/api/1.1/json/my_login/
it generates the required response generating a token like this(abridged):
HTTP/1.1 200 OK
Date: Mon, 22 Oct 2012 08:37:39 GMT
Vary: Authorization,Accept-Language,Cookie,Accept-Encoding
Content-Type: text/plain
Transfer-Encoding: chunked
OK{"success": {"my_token": "required_token"}}
But when I try the same including a header as:
curl -i -H "Content-Type:application/json" -d "username=rock&password=rock" http://my_VM_IP/api/1.1/json/my_login/
it gives me the following error:
HTTP/1.1 400 BAD REQUEST
Date: Mon, 22 Oct 2012 11:12:04 GMT
Vary: Authorization,Accept-Language,Cookie,Accept-Encoding
***Content-Type: text/plain***
Content-Language: en-us
Connection: close
Transfer-Encoding: chunked
Bad Request
I dont understand why this happens. And also why does the content-Type show text/plain, I also tried looking at some other questions like Why Setting POST Content-type:"Application/Json" causes a "Bad Request" on REST WebService? . It also addresses the same problem I have. Following the answer in that I tried giving the data in various formats as
{"username":"rock", "password":"rock"}
but without success. Thanks in advance.
By using -H "Content-Type:application/json" you're setting the Content-Type header for your request. The response will still return whatever your view tells it to return.
To return a response with Content-Type application/json, use something along these lines:
import json
from django.http import HttpResponse
def json_response(return_vars):
'JSON-encodes return_vars returns it in an HttpResponse with a JSON mimetype'
return HttpResponse(json.dumps(return_vars), content_type = "application/json")
#Usage: return json_response({'admin_token': admin_api_token.token})
You were close, but you need to send it as a JSON format via curl:
curl -i -H "Content-Type:application/json" -d '{"username":"rock", "password":"rock"}'
("password","admin" should be "password":"admin")
If that's not working, try:
curl --dump-header - -H "Accept:application/json" -H "Content-Type:application/json" -X POST --data '{"username": "admin", "password": "admin"}' http://my_VM_IP/api/1.1/json/my_login/
When you set -H parameter of curl command, you specify content type of request. Content type of response, that you see in response, is set on the server. In WSGI application you need to specify 'content-type' and 'content-length' manually. Some of framework provide utility method to return JSON responses (for example, jsonify method in Flask).