Nextjs global api calls - javascript

I am developing react based web application using NEXT.js,. As specified in NEXT.js, documentation to fetch the data before page loads, i am putting required action dispatch code in getInitialProps of the specific page. but some data fetching calls(action dispatch) like fetching authenticated user's data will be common to all the pages, so is there any way to dispatch such actions from single place before page load.
Thanks!

update, now you can use getServerSideProps and nextjs provides an easy way to get user cookie : How to use cookie inside `getServerSideProps` method in Next.js?
--------- old answer ---------
simple answer: use cookie, code refer https://github.com/nextjs-boilerplate/next.js-boilerplate https://github.com/nextjs-boilerplate/next-fetch
-- details --
I had the same question when I first adopt next.js, as it worked in react, people prefer use a token to tag authed user and fetch always run in front-end. But as next.js made ssr a build in feature, I tried and find auth by cookie is possible, and I start https://github.com/nextjs-boilerplate/next.js-boilerplate and split out a fetch based on cookie https://github.com/nextjs-boilerplate/next-fetch
-- how it works --
1.client side fetch: use fetch option option.credentials = 'include' and option.headers.Cookie=document.cookie will patch cookie into your request. Bnd when fetch back result, this become wired, you cannot access cookie header, so you have to use another header and additional logic needed in backend logic like res.header('custom-set-cookie', res.getHeader('set-cookie'))
2.server side fetch: first you need the express request object, and get cookie like req.headers.cookie, then pack it into fetch request option. when fetch back, get cookie like r.headers._headers[cookieHeaderName] and pack into response res.header('set-cookie', setCookie)
then after you pack this transfer up, you can simply call a json api and cookie will automatically transfered. And if you don't need to change cookie through header (you can through js), you can ommit the extra handle like res.header('custom-set-cookie', res.getHeader('set-cookie')) in api
you can try my ssr login here http://nextjs.i18ntech.com/login

Related

Gatsby: Re-execute page queries manually

Do you know if it's possible to re-execute Gatsby page queries (normal queries) manually?
Note, This should happen in dev mode while gatsby develop runs.
Background info: I'm trying to set up a draft environment with Gatsby and a Headless CMS (Craft CMS in my case). I want gatsby develop to run on, say, heroku. The CMS requests a Gatsby page, passing a specific draft-token as an URL param, and then the page queries should be re-executed, using the token to re-fetch the draft content from the CMS rather than the published content.
I'm hooking into the token-request via a middleware defined in gatsby-config.js. This is all based on https://gist.github.com/monachilada/af7e92a86e0d27ba47a8597ac4e4b105
I tried
createSchemaCustomization({ refresh: true }).then(() => {
sourceNodes()
})
but this completely re-creates all pages. I really only want the page queries to be extracted/executed.
Probably you are looking for this. Basically, you need to set an environment variable (ENABLE_GATSBY_REFRESH_ENDPOINT) which opens and exposes a /__refresh webhook that is able to receive POST requests to refresh the sourced content. This exposed webhook can be triggered whenever remote data changes, which means you can update your data without re-launching the development server.
You can also trigger it manually using: curl -X POST http://localhost:8000/__refresh
If you need a detailed explanation of how to set .env variables in Gatsby just tell me and I will provide a detailed explanation. But you just need to create a .env file with your variables (ENABLE_GATSBY_REFRESH_ENDPOINT=true) and place this snippet in your gatsby-config.js:
require("dotenv").config({
path: `.env.${activeEnv}`,
})
Of course, it will only work under the development environment but in this case, it fits your requirements.
Rebuild for all is needed f.e. when you have indexing pages.
It looks like you need some logic to conditionally call createPage (with all data refetched) or even conditionally fetch data for selected pages only.
If amount (of pages) is relatively not so big I would fetch for all data to get page update times. Then in loop conditionally (time within a few minutes - no needs to pass parameter) call createPage.
If develop doesn't call 'createPage' on /__refresh ... dive deeper into gatsby code and find logic and way to modify redux touched nodes.
... or search for other optimization techniques you can use for this scenario (queried data cached into json files?).

Include header when chunks are fetched with code splitting

I've used code splitting to seprate restricted parts of my app into different chunks. This is working great so far, now I would like to ensure that the files themselves don't get served unless authenticated. I was thinking of using ngx_http_auth_request_module
http://nginx.org/en/docs/http/ngx_http_auth_request_module.html#auth_request
Which allows to send a sub-request before serving certain files. How can I ensure that certain headers are always send as part of the HTTP request when React wants to fetch the necessary chunks?
I have trouble understanding why you would need to prevent unauthenticated malicious users to have access to your static chunks.
Dynamic imports and code splitting are mainly used to reduce the bundle size for large applications as users won't necessarily need everything.
In order to secure your app you need to prevent users from seeing or tampering with data they do not have access to. This means the security lies with the API your app is talking to.
What I do:
Reject unauthenticated requests to the API
Keep a token client-side on authentication
Pass and check the token on all requests
Burn the token when obsolete and redirect to login
Notify, redirect users when they do not have access to some data or better not displaying content they do not have access to
I'm sure you already did what I wrote above, what I want to emphasize is that chunks are basically empty UI filled with data from the secured API.
Let's say I have bad intentions and I bypass client-side routing in order to have access to the restricted chunk. It will be an empty UI with secured API routes, I won't be able to do anything with it.
In case you have a very specific need, you might need to write a webpack plugin.
about the ensure request
One of webpack 's properties is that it can fetch only necessary chunks when loading pages.You can just use like require.ensurn to query chunks when necessary,so there is no need to ensure the certain headers.
ngx_http_auth_request_module
Ngx_http_auth_request_module and sub-request are always used to fetch web file in server.It's always used as backend authentication module.Here is the data flow direction in nginx.
When you download file, the download request will be passed to the server, then server return the override Http Request to Nginx,then Nginx will find the exact file.
The ngx_http_auth_request_module allows to send request to back server(like php .tomcat), and based on the request to pass or not, if pass, you will be able to fetch file in the back server.
nginx-----load speed
The nginx always fetch static file, like index.html.If have to validate the permission for every js/css everytime,then fetch it throw,thd loading speed for page will be very slow.
about how to authenticate
Since you have separated app.Here is a little suggestions.You can get the authenticated request by only import restricted parts in the authenticated file.And the webpack will automatically handle the rest.
fetch data from the server in the non-restricted part with information to authenticate like this:
http://.../api/auth?info=...
based on the infos in server to authenticate, and pass other infos like type back to the frontend
based on the type information to view .
if (this.props.type === "restrict"){
<restrict component/>
} else {
<non-restrict component/>
}

ReactJS - Handle POST requests using react router dom

Is there a way to handle POST requests using the react-router-dom (npm) library?
Why? The payment gateway will redirect the user, who successfully payed, back to the platform. I can use a GET or POST request to transfer data with the redirection page. But I don't like having the data visible in the URL. Other options are always welcome, I'm using a REST API (Node.JS, Express) and a website/dashboard (ReactJS)
I get what you're after but you can't POST to the browser. If you're uncomfortable passing data as GET params in a URL, you could:
store data in LocalStorage when user submits
deliver server-rendered, static HTML upon redirect that contains purchase information
asynchronously get user's purchase data upon page load with AJAX or fetch() (or your favorite data-grabbing util).
Since you're in a React world, I'd recommend the third option here. How to fetch data, build an API endpoint, store data, then display it goes well beyond the scope of this question so I'd suggest some Googling. Here's a starting point: https://code.tutsplus.com/tutorials/introduction-to-api-calls-with-react-and-axios--cms-21027
You can handle the POST request on your express server then redirect to a static page of your app :
app.post('/payment_webhook', (req, res) => {
const paymentOk = req.body.payment // handle POST data
if (paymentOk) {
res.redirect('http://app.com/payment_success');
} else {
res.redirect('http://app.com/payment_failed');
}
});
I was discussing the same with a friend and so far we saw 2 ways of doing this:
let the payment gateway return_url be an endpoint of the backend API (rails api), which will do the commit to the payment gateway (and probably updating the order in the BD), and then it will do a redirect back to your frontend app
store the gateway trasaction token on the order object in the DB, and let the payment gateway return_url to return to a dynamic order url, therefore, react will now which order should render, then asynchronously ask the backend (rails service) to extract the token from the order object and do the commit (confirmation) and update it's status and return the order object back to react, then react can now show if the order was successful or not.
we opted for option #2, since I feel that the frontend (react) shall be the main communication gateway to our system, and the only one communicating to the backend shall be the frontend.
UPDATE: option #2 did not work since you cant do POST to a react-app therefore, we make the return_url to be dynamic, and we immediately redirect to the frontend with a url with the order_id as query param, then, the frontend when tries to load the order, in the backend we do the payment gatway confirmation, update the order object and return the updated order object to the frontend

ReactJS - how to setup login pattern?

I'm sorry if this question is a bit vague, but I'm tackling this problem for the first time and any pointer would be useful.
I am building a web app using ReactJS and I need a login system - first page with two fields username / password and submit button. The server returns a token (1234) and this needs to be used in an auth header (Authorization: Bearer 1234) in order to access the protected area.
How should I handle the login and make the browser update itself with the new content available after login?
As the others have pointed out, it is a good idea to use React-Router.
I think you can use pattern like this: You get user inputs and send them via AJAX (with JQuery, Superagent, whatever you want). If the input is valid and user authenticated, the server sends back token with some user info, which can include his roles or permissions. Based on these received data, you can use React-Router to render other component, e.g. welcome page (by calling replaceState on React-Router history object - in flux action for example).
Additionally, you should save this token in a cookie or into a session/local storage (in order to be able to use it on every subsequent request), and the user info could be stored in a Flux store. After saving this user the store emits change event, which should lead to rerender of your root component with the user information you got.
Then, based on the new user roles or permissions in your store, you can have for example ES7 decorator on some of your components deciding, if it displays the actual component or not.
Hope it helps you a bit.

Get an access token without being connected to facebook

I need to retrieve a facebook page's list of posts (feed) using their javascript SDK, just like they explain in their docs: https://developers.facebook.com/docs/graph-api/reference/v2.4/page/feed
/* make the API call */
FB.api(
"/{page-id}/posts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
I need it to be my website's "news section", so users should see it even if they are not connected to facebook.
The problem
Cool, but there is a problem... It returns: An access token is required to request this resource.
Holy cow... I'd like to get some access token for you #facebook, but my app doesn't make use of your authentication tools/plugins.
ANYWAY, I tried with FB.getLoginStatus(); but doesn't work, because the only way it can return an access_token is if the user is actually connected to the application. My users may not even be logged to facebook!
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
I've already payed a look to this SO question, but it doesn't solves my problem, simply because there are no such "generic tokens".
I've also read https://developers.facebook.com/docs/facebook-login/access-tokens/ and that also relies on tokens generated through facebook login methods... So, can't I display a list of fb page's posts in my website, without being connected into facebook, hence an application?
ADD: My app is build with angularJS, I'm not dealing with server-side code. I shall rely purely on javascript methods.
You could either use an page or an app access token, but as you'd be using them on the client-side, neither of them are an option.
See
https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
Note that because this request uses your app secret, it must never be made in client-side code or in an app binary that could be decompiled. It is important that your app secret is never shared with anyone. Therefore, this API call should only be made using server-side code.
I'd strongly recommend to build a simple server-side script (PHP for example) to proxy the request to the Graph API. You could then call this via AJAX for example and load the posts asynchronously (and alse get rid of the FB JS SDK!). There is NO way to handle this in a secure manner if you don't want to use FB Login for all of your users (which also doesn't make much sense IMHO).
I think it's straightforward :)
Since pages' posts are always public, it only needs a valid access token to retrieve page posts.
Quoting what you've written:
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
You only require an access token.
My suggestion would be;
- Generate an access token for yourself (no extra permission needed)
- request page-id/posts
This way you don't require other users to be connected to facebook, you can simply requests page-id/posts to retrieve posts with access token you generated for yourself.
I hope it solves your problem :D
TIP: As long as posts are public, you only require a valid access token, it doesn't need to be user or page specific.

Categories