I'm trying to create a gallery in React with life previews of many websites (like a portfolio) all the linked websites belong to me as well.
I already try to use iFrame and embed but I didn't have the result I would like, I'm trying to get a miniature website like in here https://codesandbox.io/explore.
Even tho the website show the thumbnails as images if you update your sandbox it will the images will update too.
I try use iFrame and embed but it does not show a small version of the website but the website as a mobile and just the frame size.
Any ideas in how I could generate such images or solve this problem in some other way?
You cant do this on the front end in a webpage. You need to execute something like puppeteer on your backend to screenshot the pages. An example can be found on
https://bitsofco.de/using-a-headless-browser-to-capture-page-screenshots/
As of the the same-origin policy, browsers do not allow you to make request to a different domain, you cannot request a different domain from your web app.
The Cross-Origin Resource Sharing standard works by adding new HTTP headers that let servers describe which origins are permitted to read that information from a web browser.
As of an alternative solution you can setup an express server and use cors package to add permission for sending request to your other site.
If you control both sites, then config Cross-Origin Resource Sharing (CORS) from server settings by adding new HTTP headers like Access-Control-Allow-Origin to be accept requests from your other servers
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
},
}
app.listen(4000, function () {
console.log('CORS-enabled web server listening on port 4000')
})
There is also a library that captures screenshot of the given url and save it to the given outputFilePath, capture-website, you can use.
Related
I need to make a request to this other website and I need to send a cookie alongside it. I have no control over this other website so I cannot modify its cors policy or allow credentials in any meaningful way.
So, I decided to convert my website to a react app that will run contained inside an electron web browser. I thought that as the electron has full control over the computer, I would be able to send a normal request without having to deal with cors, but it seems, that cors and all sorts of other protections are still enabled.
To clarify my current setup, I have:
A react website localhost:3000
A electron app showing the react website.
There is no other communication happening between the two.
All requests are made solely by the react website.
The react website needs to communicate with foreignwebsite.com and send a cookie to it.
Normally this in any server-side type of application, including electron itself, would be of no problem, but react cannot make direct requests.
One way I could do this was to potentially create a middle server that communicates with the foreigner API and friendly gives me the data I need for my front-end app. But, I don't want to host a server, and if I create a server on the client machine I think the app would be too heavy.
I could use the electron process as a server and make node.js requests with it, but to communicate between react and electron seems weirdly complicated, it feels like it would be a mess of events.
I found an answer online that tries to kind of deactivate the cors of the electron browser, it partially did work, or at least it seems that it worked, it shows no error but the cookie simply isn't transferred, maybe it just tricks the browser but it doesn't work behind the scenes, idk...
const filter = {
urls: ['http://foreignwebsite.com/*']
}
mainWindow.webContents.session.webRequest.onBeforeSendHeaders(
filter,
(details, callback) => {
details.requestHeaders.Origin = `http://foreignwebsite.com/`
details.requestHeaders.Referer = `http://foreignwebsite.com/`
callback({ requestHeaders: details.requestHeaders })
}
)
mainWindow.webContents.session.webRequest.onHeadersReceived(
filter,
(details, callback) => {
details.responseHeaders['access-control-allow-origin'] = ['http://localhost:3000']
details.responseHeaders['access-control-allow-credentials'] = 'true'
callback({ responseHeaders: details.responseHeaders })
}
)
So above it sets the AccessControlAllowOrigin and the AllowCredentials of the response accordingly and it changes the origin and referer of the requests.
And when I go make requests on the react website I do it like this:
document.cookie = 'OmegaCookie=' + cookieVal + '; path=/; SameSite=None; Secure';
let response = await fetch('http://foreignwebsite.com', {credentials: 'include'});
But the cookie is not sent. Do you know what could be going wrong or how to handle it better in this situation?
I am not sure this question already been asked here. But I could not see such a question so far.
I have a RESTapi written in Express.js.
That RESTapi is connected to a React.js web app.
RESTapi is secured with JWT authentication tokens.
In the web app, we display thousands of product items with daily prices. Someone logging into the web app and viewing few product's prices is okay.
But what is not okay is someone automates the fetch all item's prices daily and store and analytics our pricing strategies.
Basically what I want is for someone trying to access the API using a tool like a postman or something it should be blocked. Only a web browser should be able to access the API. This can be achieved to some extend by blocking the user agents. We can block POSTMON user agents but how we block all the tools like POSTMON?
Even though If we block all the tools like that still browser's dev tools network tab they can see the response.
Is there a way to encrypt the response? So network tab will display something that the users can understand. But at the same time that response can be decrypted by React.
Hope my question is clear to all!
Any help!
Thanks in advance. =)
Basically what I want is for someone trying to access the API using a tool like a postman or something it should be blocked. Only a web browser should be able to access the API.
Can't be done.
This can be achieved to some extend by blocking the user agents. We can block POSTMON user agents but how we block all the tools like POSTMON?
People can lie about the user-agent very easily.
Even though If we block all the tools like that still browser's dev tools network tab they can see the response.
Yes. Browsers are designed to work for their user's benefits above the benefits of the owners of the websites they access.
Is there a way to encrypt the response? So network tab will display something that the users can understand. But at the same time that response can be decrypted by React.
Not really. You'd have to give the decryption key to the browser, and if you give it to the browser then the user can access it.
But what is not okay is someone automates the fetch all item's prices daily and store and analytics our pricing strategies.
Consider rate limiting instead.
Essentially, however, what you are trying to do is make information public without giving it to some people.
That's a contradiction and thus impossible.
what you can do with express is to use CORS and allows only your website to reach the API.
check https://www.npmjs.com/package/cors
you gonna have something like
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://example.com',
optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for only example.com.'})
})
but to use cors for that goal probably need to use a restriction based on user-agent, to make sure that all requests are coming from a browser and with cors header.
But still not a very efficient mechanism.
The other idea is to implement some sort of 'API KEY', generated by your client-side and validated on the backend. each request needs to have an 'API KEY' as param
You need to use CORS policy with HTTPS, if the policy is set correctly in CORS policy the request will be handled only if come from the UI App, otherwise, the app will reject the requests.
hope this code snippet will assist you
const whitelist = ['http://www.example.com', 'https://www.example.com'];
const corsOptions = {
origin(origin, callback) {
if (whitelist.indexOf(origin) !== -1 || !origin) {
// !origin // allow requests with no origin (like mobile apps or curl requests)
callback(null, true);
} else {
console.error(`Not allowed by CORS, Origin ${origin}`);
callback(new Error('Not allowed by CORS'));
}
},
exposedHeaders: 'Authorization',
};
router.use(cors(corsOptions));
router.use('/api/auth', auth);
Tl;dr: I'm getting a require is not defined error in the Chrome JS console, despite having installed node.js and requrejs.
I am trying to access API keys in an external JSON file using the following code in main.js:
function readTextFile(file, callback) {
var rawFile = new XMLHttpRequest();
rawFile.overrideMimeType("application/json");
rawFile.open("GET", file, true);
rawFile.onreadystatechange = function() {
if (rawFile.readyState === 4 && rawFile.status == "200") {
callback(rawFile.responseText);
}
}
rawFile.send(null);
}
readTextFile("../secrets.json", function(text){
var data = JSON.parse(text);
apiKey = data.api_key;
username = data.username;
});
and since I use an XMLHttpRequest to the API later, which has an http:// scheme, I am looking to use CORS to work around the same-origin policy.
I put these lines at the beginning of main.js:
var cors = require('cors')
var app = express()
app.use(cors());
and my directory structure looks like this:
/project
index.html
secrets.json
/scripts
main.js
require.js
In the JS console on Chrome I get a require is not defined error. Where have I gone wrong?
This code:
var cors = require('cors')
var app = express()
app.use(cors());
Belongs in a node.js server. It is not to be run inside of Chrome. It's purpose is to help you create an http server that can ACCEPT cross origin http requests from a browser.
A browser will only allow a cross origin XMLHttpRequest if the server itself that you are trying to make the request from specifically allows that cross origin request. So, it would be whatever server that supports the URL you are trying to make the XMLHttpRequest to allows cross origin requests (typically by supporting CORS). If the server does not already support your cross origin call, you would have to either modify that server's code or make the request through some sort of proxy that you do have access to that will get the data for you and relay it back to the browser.
Where have I gone wrong?
Well, the require('cors') along with the other two lines of code you show below it are not meant to run in a browser. They run in a node.js environment and would be used to create an http server that you could then connect to from some outside agent (like a browser's web page).
From the browser, you can't do anything to MAKE a server accept cross origin requests if the server isn't already configured to do so. Your only two options are to change the target server or to use a proxy.
require() is NodeJS feature, see the link for more details.
Could You please share the command You start the app?
Try to call remote API Url but, getting Access-Control-Allow-Origin error. I tried many things like following but, nothing works.
proxy.conf.js
const PROXY_CONFIG = [
{
context: [
"/api/planets"
],
target: "https://swapi.co",
secure: false,
changeOrigin: true,
logLevel: "debug",
bypass: function (req, res, proxyOptions) {
req.headers["Access-Control-Allow-Origin"] = "*";
req.headers["X-Forwarded-Host"] = "localhost:8090";
req.headers["X-Forwarded-For"] = "localhost";
req.headers["X-Forwarded-Port"] = "8090";
req.headers["X-Forwarded-Proto"] = "http";
}
}
];
module.exports = PROXY_CONFIG;
Running with ng serve --port 8090 --proxy-config proxy.conf.js
Can't make any changes in server side because I am using third party API.
Try adding plugin like https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en in your chrome browser.
Since you cant change the server side config, so this plugin can do the trick. The browser by default blocks CORS
Since You cannot make any changes on remote server. So it can be escaped using Reverse proxy server. I also faced the same issue while calling linkedin services.
a. There is an https://cors-anywhere.herokuapp.com/ you can append this before your url
and it will temporarily resolve CORS issues.
Since in enterprise scenario you can not use herokuapp.com before your application specific names so better to set below proxy server.
b. Second approach is using rever-proxy approach and set up your own server (local or remote ) for reverse proxying.
https://stackoverflow.com/q/29670703/7562674
You can also implement reverse-proxy like implementation using Spring and Jersey.
https://github.com/hhimanshusharma70/cors-escape
As the error says, a header named Access-Control-Allow-Origin must be present in a CORS response.
Since swapi.co responses include the Access-Control-Allow-Origin header for correct CORS requests (can be tested with a simple fetch('https://swapi.co/api/planets/') from your browser's dev console), the issue may be because of your proxy settings.
Try modifying the response in the proxy bypass method:
bypass: function (req, res, proxyOptions) {
...
// Note that this is "res", not "req".
res.headers["Access-Control-Allow-Origin"] = "*";
...
}
You can't! End of story. If the owner of the api has decided not to allow cross origin requests then you can't. If your are not going to host your app on the https://swapi.co domain then you will not be able to use the api directly from Angular and you will need some kind of pass through api call on the server from .NET, Node, PHP, Java etc.
I'm developing a web application that uses the Twitter API REST. I have a page with Twitter accounts and a button for adding a new account. When the button is pressed, the function in the Angular controller is executed:
// Calls token to add a new Twitter user
$scope.callToken = function () {
$http.get('/token')
.then(function (response) {
console.log(response);
});
};
This is the code in the backend to serve de request. It simply redirects to Twitter to add a new user.
// routes.js
var token = express.Router();
token.route('/token')
.get(cuentasCtrl.getToken);
// Account file
exports.getToken = function(req, res) {
twitter.getRequestToken(function(err, requestToken, requestSecret) {
if (err)
res.status(500).send(err);
else {
_requestSecret = requestSecret;
res.setHeader('Access-Control-Allow-Origin', '*');
res.redirect("https://api.twitter.com/oauth/authenticate?oauth_token=" + requestToken);
}
});
};
But I get the next error:
Origin 'http://localhost:3000' is therefore not allowed access Twitter API
My server is running on localhost:3000 and If I put localhost:3000/token in my browser there is no problem. I have read the solutions for using CORS and tested other browsers but it hasn't worked for me. What have i done wrong?
The redirect you are sending in your express response is caught by the http client you use in the frontend and the redirect happens there. You are in a classical CORS situation and of course this is not how you can interact with the Twitter rest APIs.
You have to make http calls to Twitter on the node side (server to server) or use a client side client library for Twitter (https://dev.twitter.com/web/javascript)