Shopify PUT request failing with 404 on OPTIONS preflight - http

I am using AXIOS from within my app to access the shopify admin api. I am updating a customer with metafields (which, as I understand it, the storefront API does not support with graphql). I am receiving a preflight options error when I do a PUT. The error is a 404. The item I am trying to hit does in fact exist so I am wondering if shopify is mishandling the request or if I am missing something in my configuration.
Note: I am successfully able to do the same request through Postman. Postman is not doing an options preflight as far as I know.
My code:
axios({
method: 'PUT',
url: `https://${SHOPIFY_SHOP}/admin/customers/${decodedId}.json`,
auth: {
username: SHOPIFY_BASIC_AUTH_USERNAME,
password: SHOPIFY_BASIC_AUTH_SECRET,
},
data: {
customer: {
id: decodedId,
metafields: [
{
namespace: 'custom_fields',
key: 'organization',
value: org,
value_type: 'string',
},
{
namespace: 'custom_fields',
key: 'token_pro',
value: isPro,
value_type: 'integer',
},
],
},
},
}).then((data) => {
debugger
}).catch(( error ) => {
debugger
});
The errors
OPTIONS https://SHOP_NAME.myshopify.com/admin/customers/776734343229.json 404 (Not Found)
Failed to load https://SHOP_NAME.myshopify.com/admin/customers/776734343229.json: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'localhost:3000' is therefore not allowed access.
Note that the customer does in fact exist at the time of this axios call.

Related

Unable to make API call in NextJS app running on port different that port 3000

I am currently a CORS issue in my NextJs App. When I run the app on let's say on localhost:3030, and I make an API call to http://some-api.com, I get the following error:
Access to XMLHttpRequest at 'http://some-api.com' from origin 'http://localhost:3030' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://localhost:3000' that is not equal to the supplied origin.
I added the following lines to the next.config.js.
process.env.NEXT_PUBLIC_SOME_HOST=http://some-api.com
async rewrites() {
return [
{
source: '/api/:path*',
destination: process.env.NEXT_PUBLIC_SOME_HOST + '/:path*'
}
]
},
//avoiding CORS error, more here: https://vercel.com/support/articles/how-to-enable-cors
async headers() {
return [
{
// matching all API routes
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: process.env.NEXT_PUBLIC_SOME_HOST},
{ key: "Access-Control-Allow-Methods", value: "GET,OPTIONS,PATCH,DELETE,POST,PUT" },
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
]
}
]
},
But it still does not work.
I also attached of the response header on the OPTIONS call.
I can see that the access-control-allow-origin is set to http:localhost:3000 I think if I override that value to localhost:3030 it would work but I am not sure how to do that.
I am pretty new to NextJs, so some help would be greatly appreciated.
Updating the CorsFilter on the Back end API to allow response to http://localhost:3030 solved the problem.
My back end API is written in Spring Boot.
So I added the following:
httpServletResponse.setHeader("Access-Control-Allow-Origin", "http://localhost:3030");
Note: It also possible to allow all with "*"

Weird 401 and 403 with wordpress REST API (wp-json)

I am getting mad because as a lodded-in wordpress admin, on the front-end (not in the admin portal), I cannot make post/put requests.
A simple GET AJAX request works perfectly without any type of credentials:
axios.get(this.page.url + "/wp-json/wp/v2/posts").then((resp) => {
console.log(resp.data);
});
BUT, when I try to make post requests I always get 401 error if I do not include the nonce.
If I include the nonce, I get 403. Tried with both AXIOS and JQUERY:
// Axios:
axios.defaults.withCredentials = true;
axios.defaults.headers.post["X-WP-Nonce"] = MYSCRIPT.nonce; // for POST request
axios
.post(this.page.url + "/wp-json/wp/v2/posts", {
title: "title",
content: "content",
status: "publish",
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
// JQUERY
$.ajax({
url: this.page.url + "/wp-json/wp/v2/posts",
type: "post",
data: {
title: "title",
content: "content",
status: "publish",
},
headers: {
"X-WP-Nonce": MYSCRIPT.nonce, //If your header name has spaces or any other char not appropriate
},
dataType: "json",
success: function (data) {
console.info(data);
},
});
The nonce is simply generated with:
<script>
<?php echo 'const MYSCRIPT = ' . json_encode(
array('nonce' => wp_create_nonce('wp-rest'))
); ?>
</script>
I know this is not good practice, and I will include it properly as soon as I get it to work.
The nonce is perfectly retrieved by Javascript, but I get 403 from wordpress...
No idea on how to proceed!
The action specified in wp_create_nonce should be wp_rest (underscore), not wp-rest (hyphen).
https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/
For developers making manual Ajax requests, the nonce will need to be passed with each request. The API uses nonces with the action set to wp_rest
Replace wp-rest with wp_rest and it should work properly.

Post multiple logs to DataDog with 1 HTTP request

I want to post multiple logs to DataDog from a JS function, using a single HTTP request. Looking at the v2 docs for DataDog's 'send logs' POST endpoint, it sounds like this is possible:
For a single log request, the API ... For a multi-logs request, the API ...
But it's not clear to me from the docs how to actually send a 'multi-logs' request. I've tried the following:
const dataDogEndpoint = 'https://http-intake.logs.datadoghq.com/api/v2/logs';
const body = {
ddtags: 'env:production,status:info',
hostname: 'my-host',
message: ['My first production log.', 'My second production log.'],
service: 'my-service'
};
const response = await fetch(dataDogEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'DD-API-KEY': apiKey
},
body: JSON.stringify(body)
});
Perhaps unsurprisingly, this appears in DataDog as a single log with the following content:
[My first production log., My second production log.]
How can I achieve this?
Got it - this can be achieved by adding multiple log objects to the body like so:
const dataDogEndpoint = 'https://http-intake.logs.datadoghq.com/api/v2/logs';
const body = [{
ddtags: 'env:production,status:info',
hostname: 'my-host',
message: 'My first production log.',
service: 'my-service'
},{
ddtags: 'env:production,status:info',
hostname: 'my-host',
message: 'My second production log.',
service: 'my-service'
}];
const response = await fetch(dataDogEndpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'DD-API-KEY': apiKey
},
body: JSON.stringify(body)
});
(You'll probably want a loop instead of instantiating each log object separately.)

Nuxt js application not redirecting after successful login with WordPress REST API

I've build a login screen for a headless WordPress project.
I have used Nuxt.js for the front-end and WordPress, with JWT Auth (for token authentication), for the back-end.
Now my login is working. I successfully get the login data I want, but the redirect after this is not working. It also doesn't store the authentication data in the Nuxt.js $auth API.
I'm wondering what I need to do to make this work.
Below my code:
Login page
nuxt.config.js
auth: {
strategies: {
local: {
endpoints: {
login: {
url: 'https://clientsite.test/wp-json/jwt-auth/v1/token',
method: 'post',
propertyName: 'token'
},
user: {
url: 'https://clientsite.test/wp-json/wp/v2/users/me/',
method: 'post',
propertyName: false
},
},
tokenRequired: true,
tokenType: 'JWT',
globalToken: true,
redirect: {
login: '/login',
home: '/home',
logout: '/logout'
}
},
},
},
As you can see in the image above, the credentials are valid and I get the data I want. It just does not store the data and redirect me after this.
What am I doing wrong?
Thanks in advance!

Firebase storage upload signed URL CORS issue

I am building an app for the web hosted on Firebase where I am trying to allow unauthenticated users to upload an image to Storage (after passing a reCAPTCHA).
To do this I have a React website and a Firebase function that validates the reCAPTCHA and then generates a signed URL for the client-side code to upload the image to the default bucket. I have deployed the Function to the cloud because there is no Storage emulator I can use for local development but my React app is being served locally.
The code below omits the usual boilerplate.
Firebase Function Code:
const id = uuidv4()
const bucket = storage.bucket("project-id.appspot.com");
const file = bucket.file(id)
const expires_at = Date.now() + 300000;
const config = {
action: 'write',
version: 'v2',
expires: expires_at,
contentType: 'application/octet-stream'
};
file.getSignedUrl(config, (err, url) => {
if (err) {
console.error(err);
res.status(500).end();
return;
}
res.send(url);
});
This returns a URL to the client of the form: https://storage.googleapis.com/project-id.appspot.com/db9a5cc5-6540-4f40-933f-cfdb287b15a9?GoogleAccessId=project-id%40appspot.gserviceaccount.com&Expires=1594719835&Signature=<signature here>
Client-side Code:
Once this is received on the client-side I try to upload the file to that URL using the PUT method:
// signed_url is the url returned from the first API call to the function above.
// image_file is the file data I get from using react-dropzone.
axios({
method: 'put',
url: signed_url,
data: image_file,
headers: {'Content-Type':'application/octet-stream'}
}).then(res => {
console.log("success");
console.log(res);
}).catch((error) => {
console.log(error);
});
This is where I get a CORS error of the form: Access to XMLHttpRequest at 'https://storage.googleapis.com/project-id.appspot.com/db9a5cc5-6540-4f40-933f-cfdb287b15a9?GoogleAccessId=project-id%40appspot.gserviceaccount.com&Expires=1594719835&Signature=<signature here>' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I used cURL to see if the CORS headers in the response were being set and they were not. I then used gsutil cors set config.json gs://project-id.appspot.com to set the CORS permissions on the default bucket. Here is the format of the configuration:
[
{
"origin": ["*"],
"responseHeader": [
"Origin",
"Accept",
"x-goog-resumable",
"Content-Type",
"Access-Control-Allow-Origin",
"Access-Control-Allow-Headers",
"Authorization",
"X-Requested-With"
],
"method": ["GET, POST, PUT, PATCH, POST, DELETE, OPTIONS"],
"maxAgeSeconds": 3600
}
]
I checked the service account to make sure they had the Service Account Token Creator permission and Storage Object Creator permissions set and they did.
I followed the steps at https://cloud.google.com/functions/docs/writing/http#gcloud and I have tried every combination of content-type headers and tried v2 and v4 of getSignedURL version, as well as following any other suggestions I could find online, but to no avail.

Resources