I am trying to get this fetch method to work in Svelte
When the page.svelte calls the function to fetch the data, in the console I receive this
[HTTP/1.1 405 Method Not Allowed 19ms]
Which I have narrowed down to this
POST method not allowed
Is there a variable I need to set in the config files or is there another solution which I am missing?
// svelte.config.js
import adapter from '#sveltejs/adapter-auto';
const config = {
kit: {
adapter: adapter(),
methodOverride: {
allowed: ['POST']
},
}
};
export default config;
Both files are in the Routes folder
// fetch-data.js
export const POST = async(data) => {
const response = // get data function here
return {
body: {
data: response
}
}
}
// page.svelte
async function fetchData() {
const response = await fetch('./fetch-data', {
method: 'POST',
body: JSON.stringify(),
headers: {
'content-type': 'application/json'
}
})
const { data } = await response.json()
return data
}
The solution was to change the POST variable name to lowercase in the get-data.js file
I had the same error for a different reason, and the syntax in your question and answer has changed again so I'll add my discoveries:
+page.server.ts should no longer export const POST but instead export const actions: Actions = { ... } which don't need to return anything.
+server.ts still uses function POST(event: RequestEvent) and needs to return a Response (from the Fetch API).
Cookies can no longer be set with setHeaders but must use cookies instead. Otherwise the handler also returns 405.
I had the same problem because of old SvelteKit version (I used .456, current version at the time this was written is .484). So make sure you have the most recent version of framework, when referring to the docs ;)
Related
So this is driving me nuts because it was working at one point, and I cannot find anything I changed that would make it not work.
Here is my simple axios post request. Based on my debugging, this is successfully making the network request and the server is returning a 422 error, which I expect (testing invalid login credentials). However, when attempting to log the axios reponse to the console, I get "undefined". It is also returning a resolved promise.
const login = (loginParams) => {
return axiosLoggedOut.post("/login", loginParams);
};
Here is the code for the axios instance I am using. I am only intercepting the request in this, and I know the request it making it to the server, so I don't think the issue would be in here:
import Cookies from "js-cookie";
import axios from 'axios';
const axiosLoggedOut = axios.create({
baseURL: "http://localhost",
withCredentials: true,
});
const requestTypes = ['post', 'put', 'delete'];
const onRequest = (config) => {
if (requestTypes.includes(config.method) && !Cookies.get('XSRF-TOKEN')) {
return setCSRFToken().then(() => config);
}
return config;
}
const setCSRFToken = () => {
return axiosLoggedOut.get('/sanctum/csrf-cookie');
}
axiosLoggedOut.interceptors.request.use(onRequest, null);
export default axiosLoggedOut;
Am I missing something obvious here?
This question already has answers here:
Error when accessing API with fetch while setting mode to 'no-cors' [duplicate]
(1 answer)
XMLHttpRequest cannot load XXX No 'Access-Control-Allow-Origin' header
(11 answers)
Closed 1 year ago.
I'm trying to send a formData object to a cloudlflare workers function. Here's the original fetch event
const response = await fetch('https://example.workers.dev/createproject', {
method: 'POST',
body: formData,
mode: 'no-cors'
if (response.ok) {
...
}
else {
...
}
}
And here is my cloudflare workers index.js file
import { json, missing, ThrowableRouter, withParams } from 'itty-router-extras';
import { createClient } from '#supabase/supabase-js';
const router = ThrowableRouter();
// apiKey is the parsed JWT for a user.
// Not currently supported by Supabase's client, but eventually
// you'll be able to auth _as_ a user by providing this value.
const supabase = (apiKey) => createClient(SUPABASE_URL, SUPABASE_API_KEY);
const parseAuthHeader = (header) => {
if (!header)
return;
const [_, token] = header.split("Bearer ");
return token;
};
router.post('/createproject', async ({ request }) => {
try {
const formData = await request.formData();
console.log('success');
console.log(formData);
}
catch (error) {
console.log('error');
console.log(error)
}
console.log(headers);
console.log(request);
return new Response('test');
});
/*
This is the last route we define, it will match anything that hasn't hit a route we've defined
above, therefore it's useful as a 404 (and avoids us hitting worker exceptions, so make sure to include it!).
Visit any page that doesn't exist (e.g. /foobar) to see it in action.
*/
router.all("*", () => new Response("404, not found!", { status: 404 }))
addEventListener("fetch", event => {
event.respondWith(router.handle(event.request));
});
In the createproject route, everything that's logged comes back empty (e.g. empty objects, empty arrays) — so it's clearly not accessing the request body or formData object as expected, or I'm not sending the request / formData correctly from the original fetch call.
Can someone help me fix this code so that I can access the request body and formData inside the createproject route?
Im using a shared Axios "client" object that is passed around my application via react context, this client object has the API key auth header and base paths already configured so im not constantly defining it.
My problem is trying to use the useSwr hook, specifically when defining the fetcher. I just cannot get it to work, and im sure im missing something simple here.
Basically, I pull the api client off the context, and use a fetcher function iv defined already, but I get nothing.
Here's some snips,
The Client
const AXIOS_CLIENT_CONFIG = {
baseURL: API_BASE,
timeout: 2000,
};
export default class APIClient {
client: AxiosInstance;
accessToken: string;
headers: any;
constructor(accessToken?: string) {
this.accessToken = accessToken;
this.headers = { Authorization: `Bearer ${accessToken}` };
if (accessToken) {
this.client = axios.create({
...AXIOS_CLIENT_CONFIG,
headers: this.headers,
});
} else {
this.client = axios.create(AXIOS_CLIENT_CONFIG);
}
}
fetcher(url: string): Promise<any> {
return this.client.get(url).then((res) => res.data);
}
The Component
export default function Upload(): ReactElement {
const { api }: IAppContext = useContext(AppContext);
const { data, error } = useSwr(`/upload/${uploadId}`, api.fetcher, {
refreshInterval: 5000,
});
Using above, I see nothing, no requests, no errors. (yes, the client comes through fine, I use this throughbout my whole app, its just this fetcher part that is broken)
Just for testing if I define the following fetcher, I can see a request is made (and failed due to auth)
const fetcher = (url) => axios.get(url).then((res) => res.data);
Even logging out the function signatures, they look almost the same to me
console.log("API FETCHER", api.fetcher);
console.log("NORMAL FETCHER", fetcher);
Outputs
API FETCHER ƒ fetcher(url) {
return this.client.get(url).then(function (res) {
return res.data;
});
}
NORMAL FETCHER ƒ fetcher(url) {
return axios__WEBPACK_IMPORTED_MODULE_5___default().get(url).then(function (res) {
return res.data;
});
}
What am I doing wrong here?
After hours of screwing around, I eventually figured this out. Incase anyone else comes across the issue when trying to use an Axios client objection with class functions like I am here.
I had no bound the context of this within the class for that specific function.
Basically, I needed to add the following to my api clients constructor
// Bind "this" context
this.fetcher = this.fetcher.bind(this);
I am new to Nuxt.js and I am faced with a strange kind of issue. I have an endpoint in my backend API, allowing the end user to send a token and a new password and reset the user password.
While the request is sent correctly, and the server responding with the correct data:
In the Nuxt.js side, I have an issue, with the response data.
So, to handle all the HTTP requests using the axios, I have a class like that:
class WebAPI {
// $axios is the instance used in the Nuxt.js context
constructor($axios) {
this.$http = $axios;
}
async call(config) {
try {
///////////////////////////////////////////////////////
// HERE IS THE PROBLEM. THE FOLLOWING CONSOLE.LOG
// IT RETURNS undefined WHILE THE NETWORK RESPONSE
// RETURNS WITH DATA
///////////////////////////////////////////////////////
const result = await this.$http(config);
console.log(result);
// ...
} catch( e) {
// ...
}
}
}
And I use this class like:
const data = {
token,
new_password
};
const options = {
method: 'POST',
url : '/reset-password',
data
};
return this.webApi.call(options);
But as you probably see, in the WebAPI service, the response of the axios is undefined.
Also, it worths to mention, that the exact same WebAPI class working perfectly with other API Requests I do throughout the application.
Could you help with that issue? Do you see anything wrong?
I think you are using axios wrong. Try use $request method, like that:
async call(config) {
try {
const result = await this.$http.$request(config);
console.log(result);
// ...
} catch( e) {
// ...
}
}
I am creating a vuejs app where I am using axios to consume my rest api.
I am basically calling axios.get in various places, every time creating a new instance with the required authentication headers.
// UserdataComponent.vue
const anInstance = axios.create({
headers: {'X-API-TOKEN': store.state.token},
auth: {
username: SOME_USERNAME,
password: SOME_PASSWORD
}
})
anInstance.get(API_BASE_URL + '/userdata')
This is being done everywhere I make a rest api call.
So I wanted to move this to a separate file to keep the code DRY.
I moved the axios instance creation code to a separate file and tried exporting it as an object. This object can then be imported wherever I want to consume rest api.
I was expecting something like this to work....
// http.js
import axios from 'axios'
import store from 'store/store.js'
const HTTP = axios.create({
baseURL: API_BASE_URL,
headers: { 'X-API-TOKEN': store.state.token },
auth: {
username: SOME_USERNAME,
password: SOME_PASSWORD
}
})
export default HTTP
// UserdataComponent.vue
import HTTP from 'http.js'
...
HTTP.get('/userdata')
This gave me errors of all sorts with axios.create being returned as a string, instead of a callable function.
What should I be changing here to make it work as I want to? Should I even be using this way to modularize the http request mechanism?
Not sure if this answers you question but it's a nice way of setting it up.
If you create the axios instance in a separate file, you could export specific api calls instead, making them accessible for other components as well.
// api.js
const HTTP = axios.create({
baseURL: API_BASE_URL,
headers: { 'X-API-TOKEN': store.state.token },
auth: {
username: SOME_USERNAME,
password: SOME_PASSWORD
}
})
export default {
getSomeData () {
return HTTP.get('/endpoint')
},
postSomeData (id, name) {
return HTTP.post('/endpoint', {
id: id,
name: name
})
}
}
and then, in your component you import the api.jsand use like this:
//component.vue
import myApi from '../path/to/api'
export default {
name: 'myComponent',
methods: {
someMethod () {
myApi.getSomeData().then((response) => {
...code
})
}
}
}
I think you should use axios interceptors for this:
Axios.interceptors.request.use((config) => {
// Add stuff to the config..
// Add credentials to each request.
config.withCredentials = true
config.timeout = 10000
config.headers['Accept-Language'] = i18n.locale
config.headers['Content-Type'] = 'application/json'
return config
})
You can place this code in your main file.
Each time you do a request, this code is called and you can add your credentials to the request, so you don't have to pass the same code everywhere...
For more information check https://github.com/axios/axios#interceptors and on the web around this subject.