I know that perhaps a dedicated server would be better for this, however I’m not familiar with server only frameworks. But I’m very familiar with SvelteKit api routes. I decided to create a route named “/API” Where I have a handler class that will determine which method to run in the server based on the string passed as the func parameter in the post request. This does return the data properly when I’m using the svelte client. However, after publishing the file to Vercel It was not able to fetch the data. I will include the error message at the end since it’s very long.
Here is the “/API/+server.ts” file
import { json, type RequestEvent } from '@sveltejs/kit';
export async function POST({request}:RequestEvent){
const body = await request.json()
const handler = new API_service(body.func);
const params =body.params
let data;
if (Array.isArray(params)) {
data = await handler.function_handler(params);
} else {
// Handle the case where body.params is not an array
throw new Error("No parameters array")
}
return json( data );
}
class API_service{
private func:string;
private config = {
api_key:"&x_cg_demo_api_key=Your coingecko API Key", //<--- Change accordingly
base_url:"https://api.coingecko.com/api/v3",
currency:"?vs_currency=usd",
ids:"&ids=bitcoin",
days:"&days=30"
}
private coins_endpoint = {
markets:"/coins/markets",
}
private root_endpoint = {
ping:"/ping"
}
constructor(func:string){
this.func=func
}
public function_handler(params:any[]){
switch(this.func){
case "get_btc_ohlc":
return this.get_btc_ohlc(params[0])
}
}
private async get_btc_ohlc(id:string){
const response = await fetch(this.config.base_url+`/coins/${id}/ohlc`+this.config.currency+this.config.days)
return await response.json()
}
}
I tested the endpoint with the following client side code and I got the expected response
<script>
import {onMount} from "svelte";
onMount(async ()=>{
try {
const response = await fetch('/API',{
method:"POST",
body:JSON.stringify({
func:"get_btc_ohlc",
params:["bitcoin"]
})
})
if(!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
console.log(await response.json());
} catch (error) {
console.error('There was a problem with the fetch operation: ', error);
}
})
</script>
After using copilot extensively to solve this problem as well as looking online, I was unable to find a solution after several hour. Here are the suggestions copilot gave me
- Create a vercel.json file
- Create a hook.server.ts file
- Create a meta tag in app.html
Here they are acordingly
vercel.json
{
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "Content-Security-Policy",
"value": "default-src *; connect-src 'self' https://private-coingecko-api.vercel.app; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:;"
}
]
}
]
}
hook.server.ts
import type { Handle, RequestEvent } from '@sveltejs/kit';
export const handle: Handle = async ({ event, resolve } ) => {
const response = await resolve(event);
// Ensure response.headers exists
if (response.headers) {
response.headers.set(
'Content-Security-Policy',
"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://private-coingecko-api.vercel.app;"
);
}
return response;
};
The Meta tag in app.html
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://private-coingecko-api.vercel.app;">
The following snippet is of the actual fetch to my endpoint which returns the error following it (I Ran this from the console in the default edge blank page)
await fetch("https://private-coingecko-api.vercel.app/API",{
method:"POST",
body:JSON.stringify({
func:"get_btc_ohlc",
params:["bitcoin"],
apikey: "Your api key" //<-- I removed the middleware in the previous snippet but its still there in production
})
})
.catch(error => console.error('Error:', error));
Here is another error from postman