how to get browser full url of the page in nodejs express in environment, seems nginx issue? - spartacus-storefront

I am using a url rewriting functionality in my application(SparatcusV3.4).
I am calling my backend from node js to check a productcode exists or not
for that I need the current browser url entered by user in the address bar.
I am accessing the url using below code
const fullUrl = req.protocol + '://' + req.get('host')
this is working fine on my local system but when deployed on any environment(by SAP)
this URL is coming as "127.0.0.1:4200" , what might be the problem here with environment ?
or what is the correct way to get the full browser url entered by the user ?
any help would be appreciated!!!
thanks in advance

Please refer to this part of Spartacus docs: https://sap.github.io/spartacus-docs/server-side-rendering-coding-guidelines/#getting-the-request-url-and-origin
It suggests to use SERVER_REQUEST_URL and SERVER_REQUEST_ORIGIN injection tokens when using the setup that's running SSR behind a proxy in order to resolve URLs.
To use these optional tokens:
it is assumed you're using Spartacus' NgExpressEngineDecorator from #spartacus/setup/ssr in your server.ts file.
when injecting them, you should mark them as #Optional (per docs), as these are not available in CSR application.

const obj = {};
const rc = request.headers.cookie;
rc?.split(';')?.forEach((cookie: any) => {
const parts = cookie?.split('=');
obj[parts.shift().trim()] = decodeURI(parts?.join('='));
});
return obj;
it can give list of all cookies in request object so with OBJ['RT'] can give the value and further splitting with '=' we cna get the exact request URL there from we can extract the host and the origin uding below code
const cookieName = 'RT';
const cookieObj = this.getCookieasObject(req);
let fullURL = cookieObj[cookieName];
if (fullURL) {
fullURL = decodeURIComponent(JSON.parse(fullURL).split('=')[1]);
}
const url = new URL(fullURL);
const baseUrl = `${url.protocol}//${url.hostname}`;

Related

Express Set Custom Parameter Query Starter

I'm using express to interact with discord's oauth2 api.
When I request a user oauth token the server responds with a url like:
http://localhost:3000/index#token_type=Bearer&access_token=tkn&expires_in=int
I'm trying to extract the parameters after the # as with discords api parameters start with # unlike others which start with a ?
Because it doesn't start with a question mark I am unable to use the req.params.x property.
I thought, "No big deal, ill just get the url and extract it myself" but every single url accessor in express removes string after #. This includes req.url and req.originalUrl which both return the file path.
So how can I get url parameters started by hashtags instead of question marks?
Or How can I get the full url with content after hashtags
I was able to solve this problem by setting a custom query parser. Code snippet below.
const app = express();
app.set('query parser', (query) => {
return query.split('&').map(item => {
const [key, value] = item.split('=');
return {
key,
value
}
});
});
app.get('/', (req, res) => {
console.log(req.originalUrl); // Full URL starting with file path
})

Problem with Vue.JS to get content-disposition headers when deployed

I'm facing a problem to get an header in axios to get the file name i want to download in vue.js when it was deployed on static web apps on azure but not in Local, in local it work...
Here is the code i use to get the filename in the header.
const headerLine = response.headers["content-disposition"];
const startFileNameIndex = headerLine.indexOf('"') + 1;
const endFileNameIndex = headerLine.lastIndexOf('"');
const filename = headerLine.substring(startFileNameIndex, endFileNameIndex);
The console throw me the error that "headerLine is undefinded"... In response headers i've the content-disposition header visible.
I don't understand why it doesn't work online.
Maybe you should check the server side, see this discussion: https://github.com/axios/axios/issues/895

Cors issue solved by using proxy not working after served in Netlify Create-react-app

I have built a real estate site that makes a an api request to "https://completecriminalchecks.com" In development mode I was getting the dreaded blocked by Cors error. Through some research I found that I needed to use a proxy to solve the issue, which it did in development mode on my local host. But now I have deployed the site to netlify, I am getting a 404 error when making the request. when I look at the request from the network devtools its says
Request URL: https://master--jessehaven.netlify.app/api/json/?apikey=6s4xxxxx13xlvtphrnuge19&search=radius&miles=2&center=98144
I dont think this is right. How do i make netlify make the proper request to the api that was having cors issues in development?
Have you tried netify documentation about it?
Proxy to another service Just like you can rewrite paths like /* to
/index.html, you can also set up rules to let parts of your site proxy
to external services. Let's say you need to communicate from a
single-page app with an API on https://api.example.com that doesn't
support CORS requests. The following rule will let you use /api/ from
your JavaScript client:
/api/* https://api.example.com/:splat 200
Now all requests to /api/... will be proxied through to
https://api.example.com straight from our CDN servers without an
additional connection from the browser. If the API supports standard
HTTP caching mechanisms like ETags or Last-Modified headers, the
responses will even get cached by our CDN nodes.
You do not need to use a proxy, you enable CORRS in your server. Are you using a onde server?
If you use express something like this:
npm install --save cors
And then use it as middleware:
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
Also in your netlify.toml file this will do the trick:
# The following redirect is intended for use with most SPAs that handle
# routing internally.
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
[[headers]]
# Define which paths this specific [[headers]] block will cover.
for = "/*"
[headers.values]
Access-Control-Allow-Origin = "*"
I also faced the same issue and solved by creating a netlify.toml file in root directory.
Here is a sample code for redirect which worked for me.
Place this inside the netlify.toml file.
Documentation guide for proxy :
[[redirects]]
from = "/api/users/tickets/"
to = "https://some-external-site.com/api/users/tickets/"
status = 200
force = true
headers = {Access-Control-Allow-Origin = "*"}
[[redirects]]
from = "/api/users/cars/*"
to = "https://some-external-site.com/api/users/cars/:splat"
status = 200
force = true
headers = {Access-Control-Allow-Origin = "*"}
I also faced the same issue , so I removed the "proxy" from the "package.json" file and created a variable to store the IP addess or URL for backend , then used it with the URL parameter for calling API. The CORS issue is solved in backend by allowing "All origins".
File to store base URL:
constant.js :
export const baseUrl = "https://backEndUrl";
File to call API:
getDataApi.js:
import { baseUrl } from "./constant";
export const getProfileData = () => (dispatch) => {
axios
.get(`${baseUrl }/api/profile`)
.then((res) =>
dispatch({
type: GET_PROFILE,
payload: res.data,
})
)
.catch((err) =>
dispatch({
type: GET_PROFILE,
payload: null,
})
);
};

Control cloudflare origin server using workers

I'm trying to use a cloudflare worker to dynamically set the origin based on the requesting IP (so we can serve a testing version of the website internally)
I have this
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
if (request.headers.get("cf-connecting-ip") == '185.X.X.X')
{
console.log('internal request change origin');
}
const response = await fetch(request)
console.log('Got response', response)
return response
}
I'm not sure what to set. The request object doesn't seem to have any suitable parameters to change.
Thanks
Normally, you should change the request's URL, like this:
// Parse the URL.
let url = new URL(request.url)
// Change the hostname.
url.hostname = "test-server.example.com"
// Construct a new request with the new URL
// and all other properties the same.
request = new Request(url, request)
Note that this will affect the Host header seen by the origin (it'll be test-server.example.com). Sometimes people want the Host header to remain the same. Cloudflare offers a non-standard extension to accomplish that:
// Tell Cloudflare to connect to `test-server.example.com`
// instead of the hostname specified in the URL.
request = new Request(request,
{cf: {resolveOverride: "test-server.example.com"}})
Note that for this to be allowed, test-server.example.com must be a hostname within your domain. However, you can of course configure that host to be a CNAME.
The resolveOverride feature is documented here: https://developers.cloudflare.com/workers/reference/apis/request/#the-cf-object
(The docs claim it is an "Enterprise only" feature, but this seems to be an error in the docs. Anyone can use this feature. I've filed a ticket to fix that...)

Using Node JS to proxy http and modify response

I'm trying to write a front end to an API service with Node JS.
I'd like to be able to have a user point their browser at my node server and make a request. The node script would modify the input to the request, call the api service, then modify the output and pass back to the user.
I like the solution here (with Express JS and node-http-proxy) as it passes the cookies and headers directly from the user through my site to the api server.
proxy request in node.js / express
I see how to modify the input to the request, but i can't figure out how to modify the response. Any suggestions?
transformer-proxy could be useful here. I'm the author of this plugin and I'm answering here because I found this page when looking for the same question and wasn't satisfied with harmon as I don't want to manipulate HTML.
Maybe someone else is looking for this and finds it useful.
Harmon is designed to plug into node-http-proxy https://github.com/No9/harmon
It uses trumpet and so is stream based to work around any buffering problems.
It uses an element and attribute selector to enable manipulation of a response.
This can be used to modify output response.
See here: https://github.com/nodejitsu/node-http-proxy/issues/382#issuecomment-14895039
http-proxy-interceptor is a middleware I wrote for this very purpose. It allows you to modify the http response using one or more transform streams. There are tons of stream-based packages available (like trumpet, which harmon uses), and by using streams you can avoid buffering the entire response.
var httpProxy = require('http-proxy');
var modifyResponse = require('http-proxy-response-rewrite');
var proxy = httpProxy.createServer({
target:'target server IP here',
});
proxy.listen(8001);
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
});
proxy.on('proxyRes', function (proxyRes, req, res) {
modifyResponse(res, proxyRes.headers['content-encoding'], function (body) {
if (body && (body.indexOf("<process-order-response>")!= -1)) {
var beforeTag = "</receipt-text>"; //tag after which u can add data to
// response
var beforeTagBody = body.substring(0,(body.indexOf(beforeTag) + beforeTag.length));
var requiredXml = " <ga-loyalty-rewards>\n"+
"<previousBalance>0</previousBalance>\n"+
"<availableBalance>0</availableBalance>\n"+
"<accuruedAmount>0</accuruedAmount>\n"+
"<redeemedAmount>0</redeemedAmount>\n"+
"</ga-loyalty-rewards>";
var afterTagBody = body.substring(body.indexOf(beforeTag)+ beforeTag.length)+
var res = [];
res.push(beforeTagBody, requiredXml, afterTagBody);
console.log(res.join(""));
return res.join("");
}
return body;
});
});