angular2 - http post request parameters prevent encoding the special characters - http-post

i am trying to make a HTTP post request. When using the below code, the request parameters are null in the server side.
let url = apiURL;
let body = { 'tenantId': tenantId, 'vsLoginToken': vsLoginToken, 'branchId': branchId };
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this._http.post(url, body, options).map(res => res.json()).
catch(error => Observable.throw(error.json().error || 'Server error'));
If i remove the 'options' parameter in the HTTP post method i am getting the request parameters values. But the parameter vsLoginToken has some special characters. The original vsLoginToken value is like 'ax6a+kao+c'. But when i get this value in the server side it is like 'ax6a kao c'. As you can see the '+' characters are replaced by spaces and i want to prevent this encoding. How can i prevent this encoding? (i don't want to use URLSearchParam QueryEncoder) Any other answers will be great. Thanks

Related

Google Push notification giving ParseError

I am trying to use google push notification for calendar to be notified if a user's event's start or/and end dateTime changes.
I have followed all the steps from push doc regarding registering and verifying my domain.
My code is as follows:
#blueprint.route("/notifications", methods={'GET','POST'})
def timeBlocker():
email = '....#gmail.com'
user = User.query.filter_by(email=email).first()
thecredentials = {
'client_id': os.getenv('client_id'),
'client_secret':os.getenv('client_secret'),
'refresh_token':user.refresh,
'grant_type': 'refresh_token',
}
req = requests.post(url='https://oauth2.googleapis.com/token', data = thecredentials)
req_ = req.json()
accessToken = req_["access_token"]
print('access token is ' + accessToken)
body = {
'id': '01234567-89ab-cdef-0123456789ab',
'type': 'web_hook',
'address': 'https://dayliii.com/notifications'
}
headers = {'Authorization': 'Bearer ' + accessToken,
'Content-Type': 'application/json'
}
calendar = '....#group.calendar.google.com'
req = requests.post(url='https://www.googleapis.com/calendar/v3/calendars/....#group.calendar.google.com/events/watch', data = body, headers=headers)
return str(req.json())
Error:
{'error': {'errors': [{'domain': 'global', 'reason': 'parseError', 'message': 'Parse Error'}], 'code': 400, 'message': 'Parse Error'}}
I tried converting from double quotes to single quote as this similar post suggested yet it didn't work.
Lastly, I was curious to know if I should register & verify domain ownership of 'http://localhost:5000/' when working with push notifications in dev mode? As that's the error I am expecting to get that not sure about the way around it.
The data parameter in request() function accepts json format.
You can try converting your body variable into a json string using json.dumps().
Your request code should look like this:
req = requests.post(url='https://www.googleapis.com/calendar/v3/calendars/....#group.calendar.google.com/events/watch', data = json.dumps(body), headers=headers)

Handling base64 string as application/pdf for a single endpoint on API Gateway

We have an API that has multiple different endpoints, as you'd expect. We have the requirement to add a new endpoint which will return an application/pdf along with the file data.
To do this, we return the following:
return {
statusCode: 200,
headers: {
'Content-Type': 'application/pdf',
'Content-disposition': `attachment; filename=${filename}.pdf`,
'Accept': 'application/pdf',
},
body: fileData,
isBase64Encoded: true,
};
The isBase64Encoded only works when a binary media type is set in the API Gateway. As detailed here:
https://medium.com/#ngchiwang/aws-api-gateway-lambda-return-binary-image-ba8faa660839
The issue we have is that by setting the binary media type to * / * (no spaces) on the API Gateway, this, in turn, affects all other endpoints on the API.
Example This breaks one endpoint on the OPTIONS cors check, returning an InternalServerErrorException without reason. This endpoint is just a GET with no data in the request.
Does this mean we need a separate API just for this one endpoint, or is there a way we can include this in the same APIG?
For further clarification, this is a POST that includes a small amount of JSON in the request: {"someValue":1234} and returns the above application/pdf content type.
I'm just tackling this issue and resolved it like this:
Send base 64 string just as normal json response and handle the pdf part on the client
const sendRes = (status:number, body:any) => {
var response = { statusCode: status, headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) };
return response;
};
return sendRes(201, {pdf:your-base64-string} );
Then on the client (Nuxt in my case):
let res = await this.$store.dispatch('pdf/makePdf')
const linkSource = `data:application/pdf;base64,${res.data.pdf}`;
const downloadLink = document.createElement("a");
const fileName = "your-pdf-filename.pdf";
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
This open a download window and lets you save the file locally

Adding multiple headers to graphql client (apollo-boost)

const client = new ApolloClient({
uri,
onError: (e: any) => {
console.log('error: ', e); // Failed to fetch
console.log(e.operation.getContext()); // it does show it has x-abc-id
},
request: operation => {
const headers: { [x: string]: string } = {};
const accessToken = AuthService.getUser()?.accessToken;
const activeClientId = UserService.getActiveClientId();
headers['x-abc-id'] = activeClientId;
if (accessToken) headers['Authorization'] = `Bearer ${accessToken}`;
operation.setContext({ headers });
}
});
The problem here is when i just add Authorization header it makes the POST call and shows the expected error.
But when i add x-abc-id header which is also expected by backend it only makes OPTIONS call (no post call)
P.S. On postman adding both headers works completely fine.
Found what the issue was, thought to share if it help.
Postman does not perform OPTIONS call before sending request to backend.
In OPTIONS call, 👇represents what client call contains: [authorization, content-type, x-abc-id]
BUT what does server expects: 👇
Just authorization, content-type
So it's a calls headers mismatch (nothing related to Apollo).
x-abc-id header explicitly has to be allowed in CORS configuration on backend.
Thanks to Pooria Atarzadeh

Power Query call to google.webmaster.api , Post, request problem

I call the google.webmasters.api via Power-Query(M) and managed to configure the oath2 and made my first successfull call to get & list.
Now i try to call the /searchAnalytics/query? which is working only with Post.
This always responds in a 400 error. Formating of the Query or the Url is not working correctly.
Here some additional Infomations:
Power Query - Reference
Google Webmaster Api - Reference
PowerBi Community
format Date different:
body = "{ ""startDate"": ""2019-01-01"", ""endDate"": ""2019-02-02"" }",
to
body = "{ ""startDate"": ""2019/01/01"", ""endDate"": ""2019/02/02"" }",
let
body = "{ ""startDate"": ""2019-01-01"", ""endDate"": ""2019-02-02"" }",
AccessTokenList = List.Buffer(api_token),
access_token = AccessTokenList{0},
AuthKey = "Bearer " & access_token,
url = "https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fxxxxxxxxx.xxx/searchAnalytics/query?",
Response = Web.Contents(url, [Headers=[Authorization=AuthKey, ContentType="application/json", Accept="application/json"], Content=Text.ToBinary(body) ]),
JsonResponse = Json.Document(Response)
in
Response
getting a 400 and is shows as 400 call in Gooogle-Api Overview
Any Ideas whats wrong?
Thx
Ensure request headers are valid. Server expects Content-Type header, not ContentType.
The documentation (https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query#try-it) suggest requests should be something like:
POST https://www.googleapis.com/webmasters/v3/sites/[SITEURL]/searchAnalytics/query HTTP/1.1
Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json
Content-Type: application/json
{}
So seems like main takeaways are:
HTTP POST method must be used
Web.Contents documentation (https://learn.microsoft.com/en-us/powerquery-m/web-contents) suggests including the Content field in the options record to change request from GET to POST.
URL must be valid
You haven't provided your actual URL, so you'll have to validate it for yourself. I would get rid of the trailing ? in your url (as you aren't including a query string -- and even if you were, you should pass them to the Query field of the options record instead of building the query string yourself).
Headers (Authorization, Accept, Content-Type) should be valid/present.
Build your headers in a separation expression. Then pass that expression to the Headers field of the options record. This gives you the chance to review/inspect your headers (to ensure they are as intended).
Body should contain valid JSON to pass to the API method.
Creating valid JSON via manual string concatenation is liable to error. Using Json.FromValue (https://learn.microsoft.com/en-us/powerquery-m/json-fromvalue) seems a better approach.
All in all, your M code might look something like:
let
// Some other code is needed here, in which you define the expression api_token
AccessTokenList = List.Buffer(api_token),
access_token = AccessTokenList{0},
AuthKey = "Bearer " & access_token,
requestHeaders = [Authorization = AuthKey, #"Content-Type" = "application/json", Accept = "application/json"],
parametersToPost = [startDate = "2019-01-01", endDate = "2019-02-02"], // Can include other parameters here e.g. dimensions, as mentioned in Search Console API documentaton.
jsonToPost = Json.FromValue(parametersToPost, TextEncoding.Utf8), // Second argument not required (as is default), but just be explicit until you've got everything working.
url = "https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fxxxxxxxxx.xxx/searchAnalytics/query", // Uri.EscapeDataString function can be use for URL encoding
response = Web.Contents(url, [Headers=requestHeaders, Content=jsonToPost])
in
response
Untested (as I don't have an account or API credentials).

How to parameterize Bearer token authorization in Jmeter

I have a jmeter login script where user logs in and logs out. The detailed screenshots are attached below.
Request data is as attached:
In the response date , the authorization token is generated:
And the regular expression for the same is as below:
I am passing the value as parameter in 55/users:
When I'm running the script it is failing:
Here is the response data:
Use Header Manager to pass the Token as a Header so you would have:
See for more details:
https://stackoverflow.com/a/43283700/460802
If you're looking to learn jmeter correctly, this book will help you.
A bit easier JMeter setup (login/get):
Thread Group
HTTP Request, Body Data: { "Login":"some", "Password":"credentials" }
HTTP Header Manager: content-type application/json
JSON Extractor - Names of created variables: Token; JSON Path expression: tokenName (root level in my case)
HTTP Request
HTTP Header Manager: content-type -> application/json; Authorization -> Bearer ${Token}
Response Assertion: Fields to Test = Response Code; Pattern Matching Rules = Equals, Not; Pattern to Test 401
View Results Tree to check results
Local IE Ajax version in case...
<SCRIPT>
var baseUri = 'https://localhost:port';
var tokenUri = '/something';
var getUri = '/restrictedData';
var token;
var form = { "Login":"some", "Password":"credentials" };
postRequest(baseUri + tokenUri, form, gotToken)
function gotToken(progress) {
var response = progress.srcElement;
if (response.status != 200) {
document.body.innerText = "Error:\n" + response.response;
return;
}
token = JSON.parse(response.response);
console.log(JSON.stringify(token));
var restricted = getRequest(baseUri + getUri, token.tokenName, gotRestricted);
}
function gotRestricted(progress) {
var jsonStr = progress.srcElement.response;
var jsonObj = JSON.parse(jsonStr);
document.body.innerText = JSON.stringify(token,null,2) + '\n\n' + JSON.stringify(jsonObj,null,2);
}
function getRequest(url, token, callback) {
var xhr = new XMLHttpRequest();
xhr.onloadend = callback;
xhr.open('GET', url);
xhr.setRequestHeader('contentType', 'application/json')
if (token) xhr.setRequestHeader("Authorization", "Bearer " + token);
xhr.send();
return xhr;
}
function postRequest(url, body, callback) {
var xhr = new XMLHttpRequest();
xhr.onloadend = callback;
xhr.open('POST', url);
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(JSON.stringify(body));
return xhr;
}
</SCRIPT>
Add Bearer ${token} in HTTP Header Manager available under failing HTTP Request.
If you already have the bearer token and just want to use in in header manager then,
in HTTP HEADER MANAGER tab, put these values under NAME and VALUE column respectively.
Name: Authorization
Value: Bearer "add your actual token without quotes"
Once you've extracted the token from the token API request, use this token in the HTTP Authorization Header manager for subsequent API's. Example below:
Header Name: Header Value Authorization: Bearer ${generated_token}
Where "generated_token" is a variable containing the extracted token.
I got cUrl from my API and then I imported it.
use Authorization as parameter name and value should be
Bearer ${variable_name}

Resources