Can cloudflare add custom headers? - ajax

Is there any way to add custom headers in cloudflare?
We have some https ajax to cache static files,
but it's not handling headers like "Access-Control-Allow-Credentials" in response header and cause failure on chrome.

Scott Helme has published a way to do it using new recently released Cloudflare Workers.
https://scotthelme.co.uk/security-headers-cloudflare-worker/
let securityHeaders = {
"Content-Security-Policy": "upgrade-insecure-requests",
"Strict-Transport-Security": "max-age=1000",
"X-Xss-Protection": "1; mode=block",
"X-Frame-Options": "DENY",
"X-Content-Type-Options": "nosniff",
"Referrer-Policy": "strict-origin-when-cross-origin",
}
let sanitiseHeaders = {
"Server": "My New Server Header!!!",
}
let removeHeaders = [
"Public-Key-Pins",
"X-Powered-By",
"X-AspNet-Version",
]
addEventListener('fetch', event => {
event.respondWith(addHeaders(event.request))
})
async function addHeaders(req) {
let response = await fetch(req)
let newHdrs = new Headers(response.headers)
if (newHdrs.has("Content-Type") && !newHdrs.get("Content-Type").includes("text/html")) {
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHdrs
})
}
Object.keys(securityHeaders).map(function(name, index) {
newHdrs.set(name, securityHeaders[name]);
})
Object.keys(sanitiseHeaders).map(function(name, index) {
newHdrs.set(name, sanitiseHeaders[name]);
})
removeHeaders.forEach(function(name) {
newHdrs.delete(name)
})
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHdrs
})
}

To add custom headers, select Workers in Cloudflare.
To add custom headers such as Access-Control-Allow-Credentials or X-Frame-Options then add the following little script: -
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
let response = await fetch(request)
let newHeaders = new Headers(response.headers)
newHeaders.set("Access-Control-Allow-Credentials", "true")
newHeaders.set("X-Frame-Options", "SAMEORIGIN")
// ... and any more required headers
return new Response(response.body, {
status: response.status,
statusText: response.statusText,
headers: newHeaders
})
}
Once you have created your worker, you need to match it to a route e.g.
If you now test your endpoint using e.g. Chrome Dev tools, you will see the response headers.

cloudflare does not support this possibility

Related

Get POST request body in Vite server.proxy["/api"].configure

I am migrating a project from Webpack to Vite and have run into an issue with proxying requests to one of the endpoints in the MVC.Net backend.
Due to circumstances of the existing project, I need to handle certain calls manually - such as on initial page load of login page, check whether user is already authenticated and redirect to the main page.
I am trying to figure out how to use server.proxy.configure to handle these requests. I am managing fine with the GET requests, but I cannot seem to receive the POST request's body data.
Here is what I have at the moment:
server: {
proxy: {
"/api": {
target: "https://my.local.environment/",
changeOrigin: true,
configure: (proxy: HttpProxy.Server, options: ProxyOptions) => {
proxy.on("proxyReq", (proxyReq, req, res, options) => {
if (req.method === "GET") {
//handle simple get requests. no problems here
//...
} else {
const buffer = [];
console.log("received post request");
proxyReq.on("data", (chunk) => {
console.log("received chunk");
buffer.push(chunk);
});
proxyReq.on("end", () => {
console.log("post request completed");
const body = Buffer.concat(buffer).toString();
const forwardReq = http.request(
{
host: "https://my.local.environment",
port: 443,
method: "POST",
path: req.url,
headers: {
"Content-Type": "application/json",
"Content-Length": data.length,
},
},
(result) => {
result.on("data", (d) => {
res.write(d);
res.end();
});
}
);
forwardReq.on("error", (error) => {
console.log(error);
});
forwardReq.write(data);
forwardReq.end();
});
}
});
},
secure: false,
},
}
}
The problem is that neither proxyReq.on("data", (chunk) => { nor proxyReq.on("end", (chunk) => { ever actually trigger.
Additionally, req.body is undefined.
I have absolutely no idea where I am supposed to be getting the POST request's body.
I ended up finding a different question about the bypass option and this gave me the solution I was looking for. Ended up only handling the specific GET requests that I need to handle locally instead of forwarding to my deployed environment, and everything else gets handled automatically by vite.
"/api": {
target: "https://my.local.environment/",
changeOrigin: true,
agent: new https.Agent({
keepAlive: true,
}),
bypass(req, res, proxyOptions) {
if (req.method === "GET") {
//... here I get what I need and write to the res object
// and of course call res.end()
}
//all other calls are handled automatically
},
secure: false,
},

fastify-formbody and fastify-http-proxy are changing application/x-www-form-urlencoded request to string

I am using fastify to proxy calls to spring boot backend. Using fastify-http-proxy as proxy and application/x-www-form-urlencoded content type. To support it I am using fastify-formbody.
If I do direct call to spring boot back end, I see request like
parsedFormData=FormData{values={foo=[io.undertow.server.handlers.form.FormData$FormValueImpl#7848eda9], bar=[io.undertow.server.handlers.form.FormData$FormValueImpl#22f0cd6c]}}
But when I do call with proxy, my request is like (quotes are added for values)
parsedFormData=FormData{values={"foo=[io.undertow.server.handlers.form.FormData$FormValueImpl#7848eda9], bar=[io.undertow.server.handlers.form.FormData$FormValueImpl#22f0cd6c]}}
My proxy looks like this:
import { FastifyHttpsOptions, FastifyReply, FastifyRequest } from 'fastify';
import fastifyHttpProxy from 'fastify-http-proxy';
import * as qs from 'qs';
export class ProxyRoute {
public registerProxy(app, prefix: string, rewritePrefix: string) {
if (app.conf == undefined) {
app.decorate('conf', {});
}
app.register(fastifyHttpProxy, {
contentTypesToEncode: ['application/x-www-form-urlencoded'],
upstream: '',
prefix: prefix,
rewritePrefix: rewritePrefix,
replyOptions: {
getUpstream: () => app.conf.hostUrl,
rewriteRequestHeaders: (_req: FastifyRequest, headers: FastifyHttpsOptions<any>) => ({
...headers,
sessionID: app.conf.sessionID,
}),
},
preHandler: async (req: FastifyRequest, res: FastifyReply) => {
if (contentType && contentType.includes('application/x-www-form-urlencoded')) {
req.body = qs.stringify(req.body);
}
},
proxyPayloads: false,
});
}
}
The issue was with proxyPayload parameter. It should be removed.
Link to discussion on git.

calling back-end api (laravel) from getServerSideProps() in next js

I am using next js as a front-end and laravel as a back-end. and i want to call back-end (laravel) api from getServerSideProps() method. as shown below
export async function getServerSideProps(context) {
const response = await Axios.request({
url: 'http://localhost:8000/api/event',
method: 'get',
headers: {
Cookie: context.req.headers.cookie,
},
})
const events = response.events
console.log(response)
return {
props: { events },
}
}
so i have also set the cookie but i am getting response with message unauthenticated like below
I just wanted to say a huge THANK YOU to Riaz Kahn for his answer. After a lot of banging my face against a wall this was the answer. I'm going to post a working example of my getServerSideProps function for anyone arriving here in the future. The getUser({[configObject]}) function is just returning a promise from an axios.get('my-user/route', config) call. This is working properly in a Next 13 app using standard pages functionality (not using experimental app directory).
export const getServerSideProps = async (context: any) => {
const {req, res} = context;
try {
const {data: user} = await getUser({
headers: {...req.headers}
});
return {
props: {
fallback: {user}
}
}
} catch (e) {
res.writeHead(302, {Location: '/login'});
res.end();
}
}

How to fix slow api response in IE in reactjs using cross-fetch?

I have some apis which give very slow response in internet explore. I am fetching apis using cross-fetch in reactjs.
I have tried
1) Cache Buster in my request.
var myRequestURL = '/get/somefunction?buster='+new Date().getTime();
2) By adding header cache-control.
HttpContext.Current.Response.AddHeader("Cache-Control","no-cache,no-store")
3) By adding header
Pragma: "no-cache"
import fetch from "cross-fetch";
const { Promise } = require("es6-promise");
const API_URL = "API URL";
export default (endpoint, method = "get", body) =>
fetch(`${API_URL}${endpoint}`, {
headers: { Pragma: "no-cache" },
method,
body: JSON.stringify(body)
})
.then(response => response.json().then(json => ({ json, response })))
.then(({ json, response }) => {
if (!response.ok) {
return Promise.reject(json);
}
return json;
})
.then(response => response, error => error);
I am expecting fast response in IE like chrome browser.

React Native - Fetch call cached

I am building an app in react native which makes fetch calls that rely on the most up to date information from the server. I have noticed that it seems to cache the response and if i run that fetch call again it returns the cached response rather than the new information from my server.
My function is as follows:
goToAll() {
AsyncStorage.getItem('FBId')
.then((value) => {
api.loadCurrentUser(value)
.then((res) => {
api.loadContent(res['RegisteredUser']['id'])
.then((res2) => {
console.log(res2);
this.props.navigator.push({
component: ContentList,
title: 'All',
passProps: {
content: res2,
user: res['RegisteredUser']['id']
}
})
});
});
})
.catch((error) => {console.log(error);})
.done();
}
and the function from api.js im calling is as follows:
loadContent(userid){
let url = `http://####.com/api/loadContent?User_id=${userid}`;
return fetch(url).then((response) => response.json());
}
You can set a Header to prevent the request from being cached.
Example below:
return fetch(url, {
headers: {
'Cache-Control': 'no-cache'
}
}).then(function (res) {
return res.json();
}).catch(function(error) {
console.warn('Request Failed: ', error);
});
Manosim's answer didn't work for me, but put me on the path to a solution that did work:
fetch(url, {
headers: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': 0
}
})
This nailed it.
I had a similar problem with react native (Android) and fetch using clojurescript (instead of js).
Adding :cache "no-store" (not in the header) stopped the behavior (caching fetch data on Android App).
I think the code in js should be something like:
fetch(url, {'cache':'no-store'})
specs fetch cache-mode

Resources