Forming a JSON post request with Boost asio - http-headers

I don't usually get this low level, so I think I'm just missing something obvious with the header.
Here's the code:
request_stream << "POST / HTTP/1.1\r\n"
"Host: localhost:5000 \r\n"
"Accept: */*\r\n"
"Content-Type: application/json\r\n";
request_stream << "Content-Length: " << json.length() << "\r\n\r\n";
request_stream << json;
The resulting string is
POST / HTTP/1.1
Host: localhost:5000
Accept: */*
Content-Type: application/json
Content-Length: 34
{'key1':'value1', 'key2':'value2'}
I then send the request_stream string to the server. I can connect to the server, but it says "bad request". I'm guessing there's something wrong with the above string. Any ideas?
Thanks.

Turns out that the request was fine. The issue was the simple Flask server I set up. I was calling
print(request.get_json())
when I should've have been calling
print(request.form.get('data'))

Related

Why does this REST request work from every client except Talend API tester

This is an example of a REST POST request that works everywhere except Talend API tester. It give a 500 error.
Here is how I set the request up in my applications.
URLConnection connection = new URL("https://" + authHost + "/connect/token").openConnection();
logger.info("Connection oppened");
// message contains the form data: key=value&key=value&key=value
String message = "password=" + password + "&grant_type=password&username=" + username +
"&client_id=foolid&scope=mouthwash";
logger.info(message);
// Setting header fields.
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept", "application/json");
connection.getOutputStream().write(message.getBytes("UTF-8"));
Here is a working example in Postman
POST /connect/token HTTP/1.1
Host: identityserver.uat.example.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Cookie: ARRAffinity=6a37d2ecf3441e27913cb832c4b767c68cad0e45c8806b3c5344d1b52d57f67a; ARRAffinitySameSite=6a37d2ecf3441e27913cb832c4b767c68cad0e45c8806b3c5344d1b52d57f67a
Content-Length: 137
password=secret&grant_type=password&username=fool&client_id=foolid&scope=mouthwash
And here is what Talend say it sends, which gets the 500 error -- which I understand comes from the server.
POST /connect/token HTTP/1.1
Accept: application/json
Content-Length: 137
Content-Type: application/x-www-form-urlencoded
Host: identityserver.uat.example.com
password=secret&grant_type=password&username=fool&client_id=foolid&scope=mouthwash
What's happening here?

my request failed when the post 'content-type' is application/x-www-form-urlencoded and * form field param= { <this is a json object>}

The request is failed when I post request an API whose header content-type is 'application/x-www-form-urlencoded; charset=UTF-8' and post body is ' param = { this is a json object} '
The curl request like this, it works.
curl 'http://localhost:7272/Acme/iEhr/PersonSample' -H 'Cookie: ACMETMP=fe35925f-a243-4be9-8e73-60c461ef9bd3; JSESSIONID=47A43F4988F232CC7B53F6CF30B954F6; SESSION=e580c2c7-bf4b-45e6-93fc-de6f79854346' -H 'Origin: http://localhost:7272' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36' -H 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8' -H 'Accept: application/json, text/javascript, /; q=0.01' -H 'Referer: http://localhost:7272/route/sampleadd' -H 'X-Requested-With: XMLHttpRequest' -H 'Connection: keep-alive' --data 'param=%7B%22cityid%22%3A%222091afc3-bcd6-46d9-8033-3548ad10933b%22%2C%22areaid%22%3A%222d09f5e5-a07d-445c-9d8a-51eb436699a8%22%2C%22hosid%22%3A%220f226b63-58ad-44d7-bf23-25d0345276e1%22%2C%22deptid%22%3A%2291c176f5-63ca-4b95-87c4-9f311864ff9b%22%2C%22barcode%22%3A%221000000000%22%2C ......' --compressed
it also works with postman request but failed with Karate
Scenario: 样本登记
Given path 'iEhr/PersonSample'
And header Content-type = 'application/x-www-form-urlencoded; charset=UTF-8'
* cookies { JSESSIONID: '#(jsessionID)',SESSION: '#(sessionID)', ACMETMP: '#(acmetmpID)'}
And form fields param = {"cityid":"2091afc3-bcd6-46d9-8033-3548ad10933b","areaid":"2d09f5e5-a07d-445c-9d8a-51eb436699a8","hosid":"0f226b63-58ad-44d7-bf23-25d0345276e1","deptid":"91c176f5-63ca-4b95-87c4-9f311864ff9b","barcode":"1000000000","mothername":"manual-mother1","pregweek":"21", and so on}
When method post
Then status 200
* print response
'And form fields param = {this is a json object}'
this sentence should work but failed for us.
What is my means by karate failed ?
The response code is different compared with Karate, and it is expected result when working with postman.
Postman
the necessary param data
Karate:
18:14:09.437 request:
1 > POST http://localhost:7272/Acme/iEhr/PersonSample
1 > Accept-Encoding: gzip,deflate
1 > Connection: Keep-Alive
1 > Content-Length: 899
1 > Content-Type: application/x-www-form-urlencoded; charset=UTF-8
1 > Cookie: ACMETMP=d22c0d9a-b98b-4f6f-9e42-2f9bdffa22c8; JSESSIONID=09268B9F4CA0C15AE3FFB1A26BE424ED; SESSION=2baafdac-38d6-43d0-ac5c-d39e2b29fa48
1 > Host: localhost:7272
1 > User-Agent: Apache-HttpClient/4.5.5 (Java/1.8.0_211)
cityid=2091afc3-bcd6-46d9-8033-3548ad10933b&areaid=2d09f5e5-a07d-445c-9d8a-51eb436699a8&hosid=0f226b63-58ad-44d7-bf23-25d0345276e1&deptid=91c176f5-63ca-4b95-87c4-9f311864ff9b&barcode=1000000000&mothername=manual-mother1&pregweek=21&pregday=1&midentitycard=&birthday=2018-10-01+00%3A00&collectdate=2019-05-15+14%3A38&personsex=1&personweight=4000&address=manual-testaddress1&mobile=15397006044&collectperson=&samplequality=1&borntype=1&linkman=&fidentitycard=&labitem=PHE&sampletype=1&btn=&isfee=0&personremark=&telephone=&bednumber=&labstring=&collectnumber=&freecode=&dhosid=0f226b63-58ad-44d7-bf23-25d0345276e1&reviewtype=&diagnosticstatus=&centerid=bb717701-10de-47ee-b49e-693261c6df22&nowdeptid=07eeec75-079b-4fa9-93cf-c45ddc9a87b9&operator=%E9%BB%84%E5%86%88%E5%B8%82%E5%A6%87%E5%B9%BC%E4%BF%9D%E5%81%A5%E9%99%A2&labitems=PHE&pagecode=sampleadd&modifydetail=%E6%A0%B7%E6%9C%AC%E5%BD%95%E5%85%A5
18:14:09.557 response time in milliseconds: 120.12
1 < 200
1 < Accept-Charset: big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai ...... and so on
1 < Content-Length: 52
1 < Content-Type: text/plain;charset=UTF-8
1 < Date: Wed, 15 May 2019 10:14:09 GMT
1 < X-Application-Context: Acme.jc.test:dev:7272
[{"code":-90018,"result":"(错误-90018)失败!"}]
Can you try this,
Scenario: 样本登记
Given path 'iEhr/PersonSample'
* cookies { JSESSIONID: '#(jsessionID)',SESSION: '#(sessionID)', ACMETMP: '#(acmetmpID)'}
And def ffParams = {"param" : {"cityid":"2091afc3-bcd6-46d9-8033-3548ad10933b","areaid":"2d09f5e5-a07d-445c-9d8a-51eb436699a8","hosid":"0f226b63-58ad-44d7-bf23-25d0345276e1","deptid":"91c176f5-63ca-4b95-87c4-9f311864ff9b","barcode":"1000000000","mothername":"manual-mother1","pregweek":"21"}}
And form fields ffParams
When method post
Then status 200
* print response
Form fields are by default url-encoded only no need to explicitly mention it in header
And form field param = {"cityid":"2091afc3-bcd6-46d9-8033-3548ad10933b","areaid":"2d09f5e5-a07d-445c-9d8a-51eb436699a8","hosid":"0f226b63-58ad-44d7-bf23-25d0345276e1","deptid":"91c176f5-63ca-4b95-87c4-9f311864ff9b","barcode":"1000000000","mothername":"manual-mother1","pregweek":"21","pregday":"1","midentitycard":"","birthday":"2018-10-01 00:00" ...... and so on }
I changed to this, it works now.
I am misled by the keyword 'param' in karate and the keyword 'param' used by our product code.

Why POST endpoint not being invoked but GET endpoint is being invoked - jersey container grizzly2

I can't figure out why my GET endpoint gets called but my POST endpoint is not working. When I call curl -v -X GET http://localhost:8080/myresource/test123 it succesfully returns hello
But when I call
curl -v -X POST \
http://localhost:8080/myresource \
-H 'Content-Type: application/json' \
-d '{"test": "testvalue"}'
I keep getting this response:
* Connected to localhost (::1) port 8080 (#0)
> POST /myresource HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Type: application/json
> Content-Length: 21
>
* upload completely sent off: 21 out of 21 bytes
< HTTP/1.1 500 Request failed.
< Content-Type: text/html;charset=ISO-8859-1
< Connection: close
< Content-Length: 1031
<
* Closing connection 0
<html><head><title>Grizzly 2.4.0</title><style><!--div.header {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#003300;font-size:22px;-moz-border-radius-topleft: 10px;border-top-left-radius: 10px;-moz-border-radius-topright: 10px;border-top-right-radius: 10px;padding-left: 5px}div.body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:#FFFFCC;font-size:16px;padding-top:10px;padding-bottom:10px;padding-left:10px}div.footer {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#666633;font-size:14px;-moz-border-radius-bottomleft: 10px;border-bottom-left-radius: 10px;-moz-border-radius-bottomright: 10px;border-bottom-right-radius: 10px;padding-left: 5px}BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;}B {font-family:Tahoma,Arial,sans-serif;color:black;}A {color : black;}HR {color : #999966;}--></style> </head><body><div class="header">Request failed.</div><div class="body">Request failed.</div><div class="footer">Grizzly 2.4.0</div></body></html>%
Here is my code
import javax.ws.rs.*
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.Response
#Path("myresource")
class HelloWorldResource {
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
fun createMessage(testPost: String): Response {
return Response.status(200).entity("helllo post").build()
}
#GET
#Path("{testGet}")
#Produces(MediaType.APPLICATION_JSON)
fun getMessage(#PathParam("testGet") testGet: String): Response {
return Response.status(200).entity("hello").build()
}
}
Without seeing the actual underlying exception, it's hard to say for sure, but likely you're running into similar issues as Jersey: Return a list of strings with mismatches between a String type and a MediaType.APPLICATION_JSON produces/consumes declarations. If you're dealing in raw strings, I'd suggest using MediaType.PLAIN_TEXT, or having your post body and return value be an entity that can be represented as a non-raw-string json object (ie, something enclosed in {}), and making sure a jackson provider is registered with jersey.

Perl not playing video with vlc plugin

I am trying to play the video file with help of vlc-plugin.
Here is my code:-
#!/usr/bin/perl
use strict;
use warnings;
use File::Basename;
my $file ='/home/abhishek/Videos/lua.mp4';
my $size = -s "$file";
my $begin=0;
my $end=$size;
(my $name, my $dir, my $ext) = fileparse($file, qr/\.[^.]*/);
open (my $fh, '<', $file)or die "can't open $file: $!";
binmode $fh;
print "Content-Type: application/x-vlc-plugin \n";
print "Cache-Control: public, must-revalidate, max-age=0";
print "Pragma: no-cache" ;
print "Accept-Ranges: bytes";
print "Content-Length: $end - $begin\n\n";
print "Content-Range: bytes $begin'-'$end'/'$size";
print "Content-Disposition: inline; filename=\"$name$ext\"\n";
print "Content-Transfer-Encoding: binary";
print "Connection: close";
my $cur=$begin;
seek($fh,$begin,0);
while(!eof($fh) && $cur < $end)
{
my $buf=1024*16;
read $fh, $buf, $end-$cur;
$cur+=1024*16;
}
close $fh;
And here is my access log is writing
127.0.0.1 - - [29/Dec/2015:11:39:31 +0530] "GET /cgi-bin/download.cgi HTTP/1.1" 200 484 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0"
127.0.0.1 - - [29/Dec/2015:11:39:32 +0530] "GET /cgi-bin/download.cgi HTTP/1.1" 200 447 "-" "(null)"
As I checked what does this mean from apache site,here is what i got
If no content was returned to the client, this value will be "-". To log "0" for no content, use %B instead.
No content is returning to the client.It is returning null.
I am not able to figure out what is going wrong. Any help what will be grateful.
And please suggest me what should i do to play the video and I am not sure is this the correct way to do?
Thanks in advance
I see numerous major problems with the headers you are printing:
print "Content-Type: application/x-vlc-plugin \n";
This MIME type is primarily used in an <embed> tag to invoke VLC. The correct MIME type for this file type is probably video/mp4.
print "Cache-Control: public, must-revalidate, max-age=0";
print "Pragma: no-cache" ;
These headers, and a number of the other ones following, are missing terminal newlines (\n). This will cause them to run together, causing unexpected results.
print "Accept-Ranges: bytes";
Along with not having a newline, this header is telling the browser that this resource supports range requests. Your script doesn't actually implement this, though, which will cause browsers to get very confused.
print "Content-Length: $end - $begin\n\n";
Content-Length must be a single number representing the total length of the resource (e.g, Content-Length: $size). Also, you've got two newlines here, which will cause all the following headers to be treated as part of the content.
print "Content-Range: bytes $begin'-'$end'/'$size";
This header would normally be used with range requests, but you haven't fully implemented this feature, so this header will just confuse matters.
print "Content-Transfer-Encoding: binary";
This header is meaningless here — it's primarily used in email. Leave it out.
print "Connection: close";
This header will be set as needed by the web server. CGI scripts shouldn't generate it.
You're also missing the double newline that needs to follow the last header.
I am too lazy to get it fully working, Here is a few suggestions
which does not fit into comments
Definitely will move you forward.
# format is in the detail
my $content_length = $end - $begin;
print "Content-Type: text/html\r\n";
print "Content-Type: application/x-vlc-plugin\r\n";
print "Cache-Control: public, must-revalidate, max-age=0\r\n";
print "Pragma: no-cache\r\n" ;
print "Accept-Ranges: bytes\r\n";
print "Content-Length: $content_length", "\r\n";
print "Content-Range: bytes ${begin}-${end}/${size}\r\n";
print "Content-Disposition: inline; filename=\"$name$ext\"\r\n";
print "Content-Transfer-Encoding: binary\r\n";
print "Connection: close\r\n";
print "\r\n";
################################
#
# flush is needed
#
# ##############################
use IO::Handle;
STDOUT->autoflush;
my $cur=$begin;
seek($fh,$begin,0);
while(!eof($fh) && $cur < $end)
{
my $buf=1024*16;
read $fh, $buf, $end-$cur;
$cur+=1024*16;
##############################
# I suspect you will need this
#
###############################
print $buf;
}
close $fh;

Client credential grant type is not properly sent with Apache Oltu client library?

I tried to implement an OAuth client using OAuthClientRequest in Apache Oltu. And it seems to be that it is sending client credentials in the message body not in the Basic Auth headers according to the spec. I am not sure, I may have missed some thing in the code.
Code
OAuthClientRequest.tokenLocation("http://localhost:8081/token")
.setGrantType(GrantType.CLIENT_CREDENTIALS)
.setClientId(clientKey)
.setClientSecret(clientSecret)
.buildBodyMessage();
Request
POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_29
Host: 127.0.0.1:8081
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Connection: keep-alive
Content-Length: 127
client_secret=f921854d-f70b-4180-9fdd-3a55032103cc&grant_type=client_credentials&client_id=3f3b4092-7576-4b26-8135-980db7864c2
You might want to change buildBodyMessage() with buildQueryMessage()
The OAuth2 Bearer Token specification defines three methods of sending bearer access tokens:
Authorization Request Header Field
Form-Encoded Body Parameter
URI Query Parameter
The method buildBodyMessage() will create a request with a Form-Encoded Body Parameter. You need to use buildHeaderMessage() instead, which is also the recommended method by the specification.
Recently, I've trying to find a OAuth2 java library to get "client_credential" type of accesstoken. And below is what I have for Apache Oltu, and it seems that it is working.
#Test
public void getAccessTokenViaApacheOltuOAuthClient() {
try{
OAuthClient client = new OAuthClient(new URLConnectionClient());
OAuthClientRequest request =
OAuthClientRequest.tokenLocation(TOKEN_REQUEST_URL)
.setGrantType(GrantType.CLIENT_CREDENTIALS)
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setScope(StringUtils.join(TEST_SCOPES, " ")) //if you have scope
.buildBodyMessage();
String token =
client.accessToken(request, "POST", OAuthJSONAccessTokenResponse.class)
.getAccessToken();
System.out.println(token);
assertTrue( token != null);
} catch (Exception e) {
e.printStackTrace();
}
}