I am using google custom search api to search for images in angular.js project.
Here is my Code:
var photosPublic = $resource('https://www.googleapis.com/customsearch/v1',
{ key: '..........ZDtw95C0V98ne4S39SPFi68', cx: '..........75325342:1ttvll7gahc' },
{ searchType:'image' });
return {
search: function(query) {
var q = $q.defer();
photosPublic.get({
q: query
}, function(resp) {
q.resolve(resp);
}, function(err) {
console.log(err);
q.reject(err);
})
return q.promise;
}
}
If i enter url plus all credentials directly in browser it works perfectly fine. But when i include this in my project i receive following response:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "authError",
"message": "Invalid Credentials",
"locationType": "header",
"location": "Authorization"
}
],
"code": 401,
"message": "Invalid Credentials"
}
}
What am i doing wrong?
i had the same issue and wanted to share my solution here because i stumbled here from google search.
the problem appears when you set some default authorization headers in request libraries like $resource or axios etc...
When you provide an Authorization header in the request you're sending to google custom search api the google server is trying to authorize you with this header and isn't even trying to authorize you with the given key and cx.
I don't know much about $resource (maybe someone else could add some code?) but i have a solution for axios:
import axios from 'axios'
export default {
url: 'https://www.googleapis.com/customsearch/v1',
http: axios.create(),
search(text) {
this.http.defaults.headers.common = {};
const key = process.env.GOOGLE_SEARCH_API_KEY
const cx = process.env.GOOGLE_SEARCH_SCOPE_ID
return this.http.get(this.url, {
params: {
q: text,
cx,
key
}
})
}
}
This creates an own axios instance for the search api and resets the headers. Plus: your global axios instance is not affected (perhaps your Auth headers is needed for the communication with your backend).
Related
I am trying to get request from api that has a owner = value and date = value. Using Postman I can send a request with body json to get results. However when using Axios I can not get the results. How do I send body json to header and get results back. with Axios I am getting an empty response
does not work
var searchRecord = {
owner: 'wxTWH8zqSwaIXPAVsjZoRCkvjx73',
date: '2021-09-02',
};
var config = {
method: 'get',
url: 'http://localhost:3000/records/owner',
headers: {
'Content-Type': 'application/json',
},
body: searchRecord,
};
axios
.get('http://localhost:3000/records/owner', config)
.then(function (response) {
// handle success
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
})
in Postman I can send the following in the body and get the results I need
{
owner: 'wxTWH8zqSwaIXPAVsjZoRCkvjx73',
date: '2021-09-02',
}
output response will be:
{
"instantMessage": "false",
"isComplete": false,
"_id": "612e5cede496ce8f1b6a244c",
"date": "2021-08-31",
"title": "Ming first",
"description": "Test",
"remindTime": "1630432800",
"owner": "wxTWH8zqSwaIXPAVsjZoRCkvjx73",
}
I think I have the same problem.
When I'm using the postman to test my backend - everything work ok.
So the purpose is to get data from endpoint (and as body I want to provide user email):
data = {
"user_email": test#test.com
}
.get("api/test_endpoint/", config, data)
How to send body data and headers with axios get request?
Last comment in above topick "GET Body is allowed by the standards past 2014".
So finally is it possible or is it a correct practice?
Edit:
Of course I have to add:
It's possible to add needed data as part of get request url (but it's could not be login or pass!!!)
So for example logged in admin user has possibility to get data for some user via email like:
get('localhost/api/test_endpoint?user_email=test#test.com')
So why not use body as part of get request?
for the last three days I got stuck at this problem and it is getting very frustrating. I don't know what else to try.
I am running a Sails app on localhost:1337 and a create-react-app on localhost:3000.
I enabled csrf on the backend and followed the sails documentation to implement it.
I have created the route
'GET /grant-csrf-token': { action: 'security/grant-csrf-token' } and it works fine, I get the token. If I use postman the token is accpeted and my login form works.
In React however, I receive the token but I get 403 Forbidden error when I submit the post request to login.
useEffect(async () => {
let csrfToken;
try {
let csrfTokenRequest = await Axios.get(
`${state.serverUrl}/grant-csrf-token`
);
csrfToken = csrfTokenRequest.data["_csrf"];
dispatch({
type: "csrf",
value: csrfToken,
});
} catch (err) {
dispatch({
type: "flashMessage",
value: "There was an error.",
});
}
}, []);
I tried various ways to send the token with my post request:
await Axios.post(
`${appState.serverUrl}/login`,
{
emailAddress,
password,
_csrf: appState.csrf,
},
{ withCredentials: true }
);
I also tried setting it as a default header like so:
Axios.defaults.headers.post["X-CSRF-Token"] = appState.csrf;
and set cors allowRequestHeaders parameter to allowRequestHeaders: 'content-type, X-CSRF-Token',
I also tried sending it as a query parameter
`/login?_csrf=${encodeURIComponent(appState.csrf)}`
I also tried various cors settings inside Sails, currently it is setup like so:
cors: {
allRoutes: true,
allowOrigins: [
'http://localhost:3000',
],
allowCredentials: true
}
So just to clarify once again:
The /grant-csrf-token route works fine. I am receiving the token
It works in Postman
In React I get 403 error
Could you try something like that:
Send the csrf in header and allow Sails to process the request header.
// config/security.js
cors: {
allRoutes: true,
allowOrigins: ['http://localhost:3000'],
allowCredentials: true,
allowRequestHeaders: ['content-type', 'x-csrf-token', 'authorization'],
},
I have a simple upload form which onsbubmit should post data to API. In my previous question I struggled to get it running in general, but now CORS went into play. After spending hours on configuring CORS back an forth on Azure Function I got stuck. Finally I managed to verify the server with Curl (Allow Access Origin is matching). This made me thinking there is a bug/feature in how axios handles the requests. So I used fetch just before axios. When deployed one POST fire was successful. I thought I found the problem - so I commented out the axios part. Deployed again. Nothing. So I am back with the working solution but really dirty - one of the methods is firing Error. The other is working. I think the working one is the second one. Any ideas what is happening here?
Here is my code snippet:
formHandler() {
const { formFields } = this.state;
console.log(formFields);
const response = fetch('https://example.com', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(formFields),
})
axios({
url: 'https://example.com',
method: 'post',
headers: { 'Content-Type': 'application/json'},
data: formFields
}).then(function(response){
console.log(response);
//Perform action based on response
})
.catch(function(error){
alert(error);
console.log(error.status);
//Perform action based on error
});
}
}
and this is the function.json content on Azure:
{ "bindings": [ { "authLevel": "function", "type": "httpTrigger", "direction": "in", "name": "req" }, { "type": "http", "direction": "out", "name": "res" } ] }
I have enabled the methods in the platform features of Azure Function. Should this automatically propagate to function.json? Or should I add this manually?
Axios sends an OPTIONS request prior to sending the POST. It's likely that the Azure Function is denying the OPTIONS request, which prevents the POST request from being successful. Read more about the OPTIONS verb here and here. However, it looks like your function.json is missing a methods key that should have a value of [ "options", "get", "post" ]. This will explicitly allow both OPTIONS and POST (as well as GET).
Your Azure Function's function.json should be something like this:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"options",
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
For all those who struggle with similar issue the workaround is relatively simple. Stick to content-type application/x-www-form-urlencoded and avoid custom headers, this way it will not force preflight with OPTIONS.
There seems to be a bug either in Axios package and/or Azure Functions on handling posting/responding to OPTIONS call. Check out: https://medium.com/#praveen.beatle/avoiding-pre-flight-options-calls-on-cors-requests-baba9692c21a
for some other related hints.
In firefox I noticed that Option call from Localhost has Origin: null. This maybe AXIOS bug and Azure Function does not accept this call as proper Options call. But I stopped further investigation on his.
I've read the Twilio documentation and I can't find a way to send a simple SMS from the frontend using JavaScript/React.
The Twilio documentation just shows how to do that using Node.js(server side).
Actually, I found the documentation a bit awkward because they don't explain the how to do that using the most common programme language on the web.
I'm using postman and it works fine, but on my react code doesn't.
The code below was exported from Postman:
var settings = {
"async": true,
"crossDomain": true,
"url": "https://api.twilio.com/2010-04-01/Accounts/AC62761f2bae5c5659cc5eb65d42e5d57e/Messages.json",
"method": "POST",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic hashedAuthToken",
"Cache-Control": "no-cache",
"Postman-Token": "0s41f5ac-2630-40c4-8041-1e5ee513f20d"
},
"data": {
"To": "+353838173123",
"From": "+18634000432",
"MessagingServiceSid": "MG3d622e63a343e11a2032b1414560f227",
"Body": "Test, hi"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
PS: The tokens above was modified. It won't work if you are not using your own credential.
Twilio developer evangelist here.
There is a huge problem with what you are trying to attempt here.
Putting your Twilio credentials into the front end (or into a Stack Overflow question/answer) leaves them open to anyone to read your source code and steal them. A malicious attacker can take those credentials and abuse your account with them.
I recommend you refresh your Auth Token in your Twilio console now. You should consider them compromised.
What you should do is build an SMS sending service on your own server side and then call that service from your React front end. There is a blog post on sending SMS with Twilio on React that is worth reading and I will try to put something together to show it too.
Update:
I wrote a blog post explaining how to send an SMS with React and Twilio. The important thing is that you should perform the API call in your server (in the blog post, it's an Node.js/Express server but you can use whatever server-side tech you want). Then you send the message from your React application to the server using fetch (or axios or XMLHttpRequest if you want).
You can use the method below to do that easily.
sendSMSTwilio(message) {
const url = Config.sms.url;
const accountSid = Config.sms.accoundId;
const authToken = Config.sms.authToken;
const auth = 'Basic ' + new Buffer(Config.sms.accountSid + ':' + Config.sms.authToken).toString('base64');
const details = {
To: message.to,
From: message.from,
MessagingServiceSid: Config.sms.serviceSid,
Body: message.text
};
const formBody = [];
for (var property in details) {
const encodedKey = encodeURIComponent(property);
const encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + '=' + encodedValue);
}
const body = formBody.join('&');
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
Authorization: auth
},
body
};
return new Promise((resolve, reject) => {
return fetch(url, options)
.then((response) => {
return resolve(response);
})
.then((responseJson) => {
return resolve(responseJson);
})
.catch((error) => {
return reject(error);
});
});
}
You can call and receive the promise response like that:
this.sendSMSTwilio()
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log('Error SMS sender', err);
});
I'm having this trouble of handling error responses in AngularJS while using $resource. My setup works perfectly with status 200 responses, but when the API throws out a 400 error I just get an empty object.
This is my controller:
$scope.createProduct = function() {
Api.product.save($scope.product).$promise.then(
function(res) {
console.log(res);
},
function(error) {
console.log(error);
}
)
}
This is my Api service:
function ApiService($resource, API_URL) {
return {
product: $resource(
API_URL + '/product/:product_id', { 'product_id': '#product_id' },
{
show: { method: 'GET' },
update: { method: 'PUT', headers: {'Content-Type': 'application/json'} },
}
),
}
}
This is what console.log(error) prints out after a 400 error:
Object {data: null, status: -1, config: Object, statusText: ""}
And finally this is the error response API spits out which I don't get:
{
"errors": {
"message": [
"The town field is required.",
"The postcode field is required.",
]
}
}
Any help would be appreciated, thanks!
EDIT: As an example try sending a POST request to https://api.twitter.com/1.1/statuses/destroy/1.json. If I do this on Postman, I get this error message:
{
"errors": [
{
"code": 215,
"message": "Bad Authentication data."
}
]
}
How do I get this response and the string "Bad Authentication data." in Angular? For some reason I can not do this with my current setup.
The issue may relate to interactions between your API server and CORS.
I am running a Flask based API backend that was presenting this same issue. Troubleshooting led me to discovering that my API was performing a TCP RST when receiving the POST request in around 9 out of 10 connections.
Wireshark capture
The Flask server was logging that the response was being sent back correctly.
2018-08-19 13:26:59,104 INFO: 127.0.0.1 - - [19/Aug/2018 13:26:59] "POST /users/test HTTP/1.1" 419]
Cause
The the cause of the issue was rejecting the POST request in the API backend without reading the POST data first. I refactored my API to always read POST data and this solved the problem.
It's not clear to me how CORS effects this situation, however this problem was only seen when making calls through Angular instead of directly to the API.
The following StackOverflow question pointed me in the right direction to solve this.
No response with POST request and Content-Type "application/json" in flask