This is regarding to my project, Where I am write Poco SSL client to communicate with a server.
I am able to do (i) Basic Auth (ii) Cert exchange. But after sending post request I am facing "Error 500".
Let me explain it=>
I have a working curl:
curl -d '{"name":"com.my.session.value"}' -H 'Content-Type: application/json' -H 'Accept: application/json' -E MyCert.pem --key MyKey.pem -u testuser -k -vvv https://<server-ip>:<port>/Internal/directory/path
using this I am able to print data on console. So tried to write same in Poco/C++:
// I have handler for keyPassparse, cert, invalid-cert-handler and used them in below line
SSLManager::instance().initializeClient(parse_str, Cert, ptrContext);
URI uri(argv[1]);
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort());
session.setKeepAlive(true);
Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_POST, uri.getPath(), Poco::Net::HTTPMessage::HTTP_1_1);
HTTPBasicCredentials cred("testuser", "secret");
//Here I tried to add headers and data
cred.authenticate(req);
req.add("Content-Type","application/json");
req.add("Accept","application/json");
req.add("data","com.my.session.value"); // try-1 to add data
req.setKeepAlive(true);
std::ostream& myOStream = session.sendRequest(req);
std::string body("name=com.my.session.value"); // try-2 to add data
myOStream << body;
Poco::Net::HTTPResponse response;
std::istream& rs = session.receiveResponse(response);
std::cout << response.getStatus() << " " << response.getReason() << std::endl;
}
catch (Exception& exc)
{
std::cerr << exc.displayText() << std::endl;
return 1;
}
return 0;
}
This is always returning Error:500 (Internal server error)
Which means my data section is not reaching properly.
Please suggest me a way to pass proper "data" section to server.
Thanks in advance.
I found the solution for this:
1) I sent data as json:
Poco::JSON::Object obj;
obj.set("name", "com.my.session.value");
std::stringstream ss;
obj.stringify(ss);
2) Content herders should not be added by "add", used below for them:
req.setContentType("application/json");
req.setContentLength(ss.str().size());
3) Now sending body like this:
std::ostream& myOStream = session.sendRequest(req);
obj.stringify(myOStream);
Approach used:
I wrote code for http.
Sent same data by curl and exe, captured packets for both.
Compared and fixed gaps one by one.
I hope this will help someone in future.
Related
I am trying to create a new resource in keycloak
on keycloak UI I looged in with admin account then I created a realm called demo and a user abc in it and created a client clientA after that I have created a new resource named resourceA with scopes and policy and permissions
while on keycloak ui everything is working fine resource was created the user abc has realm roles as admin, uma_authorization and client role of the client clienA is uma_protection
when i try to create a resource via rest api i am getting {"error":"unknown_error"}
Here are the steps I am following
obtained a pat as shown here
curl -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'grant_type=client_credentials&client_id=clientA&client_secret=given client secret' \
"http://localhost:8080/auth/realms/demo/protocol/openid-connect/token"
I got the access token (pat) then I followed next step
curl -v -X POST \
http://localhost:8080/auth/realms/demo/authz/protection/resource_set \
-H 'Authorization: Bearer '$here i am adding the pat i received from the previous step \
-H 'Content-Type: application/json' \
-d '{
"resource_scopes":[
"read-public",
"post-updates",
"read-private",
"http://www.example.com/scopes/all"
],
"icon_uri":"http://www.example.com/icons/sharesocial.png",
"name":"Tweedl Social Service",
"type":"http://www.example.com/rsrcs/socialstream/140-compatible"
}'
I got {"error":"unknown_error"} as a response with status code 400 Bad request. What am I missing here ?
I know what it feels like :)
Reason
org.keycloak.services.error.KeycloakErrorHandler gets error text from WebApplicationException::getMessage method result.
public Response toResponse(Throwable throwable) {
//...
error.setError(getErrorCode(throwable));
//...
}
private String getErrorCode(Throwable throwable) {
if (throwable instanceof WebApplicationException && throwable.getMessage() != null) {
return throwable.getMessage();
}
return "unknown_error";
}
And if caused exception is another type of RuntimeException you will get "unknown_error"
Solution (short path):
Extend WebApplicationException and implement your own constructor and getMessage method like that:
public class CustomException extends WebApplicationException {
private final String message;
public AbstractUserException(Throwable throwable) {
// log exception if you want
this.message = throwable.getMessage();
}
#Override
public String getMessage() {
return message;
}
}
Wrap the main code of your resource in the try catch block, which always will throw your custom Exception
try {
// your code
} catch (Exception e) {
throw new CustomException(e);
}
Voila! You will get a readable error in response
P.S. If you want to go further - you can throw your exception with a complete HTTP Response object, which may contain custom HTTP status code, etc
I am trying to build a gnome shell extension (using gjs) that I need to communicate with an external REST API. In order to do so, I need to accompany my requests with the header: Authorization: Bearer <token> and with a Content-Type: application/json.
I have looked all over for questions like this and I did find some similar ones but none of them works. The documentation is not helpful at all, and, if anything, it has only confused me more.
With curl I could send that request as follows:
curl -X GET -H "Authorization: Bearer <token>" -H "Content-Type: application/json" <url>
So far, I have only created extensions that send simple GET requests with no headers. Then I would do the following:
const Soup = imports.gi.Soup;
let soupSyncSession = new Soup.SessionSync();
let message = Soup.Message.new('GET', url);
let responseCode = soupSyncSession.send_message(message);
let res;
if(responseCode == 200) {
res = JSON.parse(message['response-body'].data);
}
Any idea on how I can add the headers? Any help would be appreciated!
EDIT:
By using #ptomato's answer I ended up using the following code:
function send_request(url, type='GET') {
let message = Soup.Message.new(type, url);
message.request_headers.append(
'Authorization',
`Bearer ${token}`
)
message.request_headers.set_content_type("application/json", null);
let responseCode = soupSyncSession.send_message(message);
let out;
if(responseCode == 200) {
try {
out = JSON.parse(message['response-body'].data);
} catch(error) {
log(error);
}
}
return out;
}
Initial Comment:
So, I managed to find a workaround but it is not efficient and so I will not mark it as the accepted answer. If anyone knows how to answer my question using Soup, please answer!
My workaround involves using the imports.misc.util file which includes the function spawnCommandLine for executing shell commands. So, I used curl in order to download the json to a file (the path variable below):
Util.spawnCommandLine(`/usr/bin/curl -X ${type} -H "Authorization: Bearer ${token}" -H "Content-Type: application/json" ${url} -o ${path}`);
and then I read the contents by using the following:
let text = GLib.file_get_contents(path)[1];
let json_result = JSON.parse(text);
This is not efficient at all and there should be an easier way around. But, until that is found, I hope this will be able to help someone else.
message.request_headers is a Soup.MessageHeaders object to which you can append() the authorization and content type headers.
Additionally there is a convenient set_content_type() method for the content type header specifically.
The documentation and help for this particular Segment.io is limited and sparse, so I hope it's OK to ask in here.
I have just set up a Segment.io workspace and a HTTP API source
Per the docs, I sent some POST requests (with Postman) to the https://api.segment.io/v1/track and https://api.segment.io/v1/page endpoints. The requests were structured like this:
curl -X POST \
https://api.segment.io/v1/track \
-H 'Accept: */*' \
-H 'Authorization: My4w3s0m3k3y' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json' \
-H 'Host: api.segment.io' \
-H 'Postman-Token: 474d7fbe-15af-43d2-b629-61e15945e662,2c3d5fbe-2c09-4fe6-b7ea-a04e3221201b' \
-H 'User-Agent: PostmanRuntime/7.11.0' \
-H 'accept-encoding: gzip, deflate' \
-H 'cache-control: no-cache' \
-H 'content-length: 117' \
-d '{
"userId": "abc123",
"event": "My tests",
"properties": {
"name": "test 1"
}
}'
which all returned a 200 response and the following message:
{
"success": true
}
However, when I got to my dashboard, no events have been recorded.
The debugger is also empty
What am I missing here?
It looks like your write key isn't base64 encoded. When you encode your write key, remember to add the : at the end of it, before it's encoded.
Also, for the Authorization key:value, be sure to add Basic before the encoded write key. So your Authorization key:value would look like:
Authorization: Basic {encoded write key}
An example from the segment documentation:
In practice that means taking a Segment source Write Key,'abc123', as the username, adding a colon, and then the password field is left empty. After base64 encoding 'abc123:' becomes 'YWJjMTIzOg=='; and this is passed in the authorization header like so: 'Authorization: Basic YWJjMTIzOg=='.
I have been dealing with the same issue.
I found the solution as Todd said.
You should add a header Authorization: Basic + base64 encoding write key.
So, you look for the Segment source setting and get the write key.
After that, i have used an online base64 encoding tool to encode my write key.
Finally, you should add this header (Authorization) with 'Basic' and the encoded write key.
You should be able to see the tracked event in the Debugging panel in Segment web page.
I hope this helps!
You can try this code
const { promisify } = require("util");
var Analytics = require("analytics-node");
var analytics = new Analytics("xxxxxxxxxxxxxxxxxxxxxxx", {
flushAt: 1,
});
const [identify, track] = [
analytics.identify.bind(analytics),
analytics.track.bind(analytics),
].map(promisify);
console.log("user id: ", req.body.event.app_user_id);
let app_user_id = req.body.event.app_user_id;
let period_type = req.body.event.period_type;
let expiration_at_ms = req.body.event.expiration_at_ms;
let ret = "Initial";
try {
await identify({
userId: app_user_id,
traits: {
period_type: period_type,
expiration_at_ms: expiration_at_ms,
},
});
ret = "Done : Sengment done";
} catch (err) {
console.log("err: ", err);
ret = "Error : " + err;
}
return {
rafsan: ret,
};
Try to clear your browser's cache or use a different browser. I had the same problem and worked for me.
Hope this helps.
I encounter an issue when I try to use the Paypal sandbox API.
I've created my 2 sandbox accounts (the facilitator and the buyer), and I've created my app to get the credentials.
Then, I use the curl example provided by Paypal to get a token :
curl -v https://api.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-H "Accept-Language: en_US" \
-u "my-client-id:my-secret" \
-d "grant_type=client_credentials"
I get a 200 response, with an "access_token".
Then, I use this access token to get another resource, for example :
curl -v -X GET https://api.sandbox.paypal.com/v1/invoicing/invoices?page=3&page_size=4&total_count_required=true \
-H "Content-Type: application/json" \
-H "Authorization: Bearer the-token-received-above"
Then, I get a 401 error :
{
"name":"AUTHENTICATION_FAILURE",
"message":"Authentication failed due to invalid authentication credentials or a missing Authorization header.",
"links":[{
"href":"https://developer.paypal.com/docs/api/overview/#error",
"rel":"information_link"
}]
}
I don't understand what I'm doing wrong, since I've followed every step decribed in the Paypal doc (at least, I think I have... probably not)
Thanks for your help
curl -v -X GET "https://api.sandbox.paypal.com/v1/invoicing/invoices?page=3&page_size=4&total_count_required=true" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer the-token-received-above"
Actually had this exact same issue but didn't know what was wrong with my curl. For me, the issue was I forgot to put "Bearer" in the Authorization section.
For this, you are required to wrap the URL with quotation marks.
After get access_token. Please try this
try {
$params = array('access_token' => $jsonResponse->access_token);
$userInfo = OpenIdUserinfo::getUserinfo($params, $this->_api_context);
} catch (Exception $ex) {
ResultPrinter::printError("User Information", "User Info", null, $params, $ex);
exit(1);
}
ResultPrinter::printResult("User Information", "User Info", $userInfo->getUserId(), $params, $userInfo);
Don't forget to add
use PayPal\Api\OpenIdTokeninfo;
use PayPal\Api\OpenIdUserinfo;
That's worked for me.
I am sending this body via API POST to extractor I created with app.
{"input":{"website/url":"http://www.targetsite.com/"}}
No matter what URL I put in, it always returns me the results from the same page (I think it must be the one I trained it on). I can put any string in there and it just totally ignores it.
GET works fine but I would much rather use POST.
Anyone know why this isn't working?
this should work, here is a worked example
curl -b authcookie -XPOST 'https://api.import.io/store/data/f53e3905-c5d0-457a-befd-d13a3a421bcf/_query' -d '
{
"input": {
"webpage/url": "http://www.ikea.com/us/en/search/?query=chair"
}
}
'
compared to:-
curl -b authcookie -XPOST 'https://api.import.io/store/data/f53e3905-c5d0-457a-befd-d13a3a421bcf/_query' -d '
{
"input": {
"webpage/url": "http://www.ikea.com/us/en/search/?query=light"
}
}
'
table versus light results. If you look in the json of the response it should tell you the url that the results are returned from:-
"pageUrl": "http://www.ikea.com/us/en/search/?query=light",
You can also try out this yourself on our api docs:-
http://api.docs.import.io/#!/Query_Methods/queryPost