react-pdf cors to gcp storage - reactjs

I want to get pdf file from my GCP , but I get CORS error. Ok , np . I've tried to find how to solve this issue in GCP . Found this example :
https://bitmovin.zendesk.com/hc/en-us/articles/360000059353-How-do-I-set-up-CORS-for-my-Google-Cloud-Storage-Bucket-
I've following all of this instructions :
echo '[{"origin": ["*"],"responseHeader": ["Content-Type"],"method": ["GET", "HEAD"],"maxAgeSeconds": 3600}]' > cors-config.json
gsutil cors set cors-config.json gs://booknote-pdf-files-store
import React, { useState } from 'react'
import { Document, Page } from 'react-pdf'
import { withStyles } from '#material-ui/styles'
import PropTypes from 'prop-types'
import CircularProgress from '#material-ui/core/CircularProgress'
import styles from './styles'
const Application = ({ classes }) => {
const [numPages, setNumPages] = useState(null)
const [pageNumber, setPageNumber] = useState(1)
const onDocumentLoadSuccess = ({ numPages }) => {
setNumPages(numPages)
}
return (
<div className={classes.container}>
<Document
file="https://storage.cloud.google.com/booknote-pdf-files-store/living_in_the_light.pdf"
onLoadSuccess={onDocumentLoadSuccess}
renderMode="svg"
loading={<CircularProgress />}>
<Page pageNumber={pageNumber} />
</Document>
</div>
)
}
Application.propTypes = {
classes: PropTypes.instanceOf(Object).isRequired,
}
But i still get CORS error. What am I doing wrong ? If you need additional info , pls let me know
Also you can check npm package which I use for this purpose :
https://www.npmjs.com/package/react-pdf

Assuming that the gsutil command for setting up cors actually worked ( I'd double-check just to be sure, run: gsutil cors get gs://booknote-pdf-files-store and see if the changes have been reflected ). Simply put, react-pdf relies a lot on PDF.js and so it is possible that this is caused by how PDF.js gets the file from the server.
Taken straight from PDF.js FAQ, "PDF.js runs with the same permissions as any other JavaScript code, which means it cannot do cross origin requests".
There are a few workarounds available at your disposal though, one of them is using a proxy that return the Access-Control-Allow-Origin header if it's not at the Same Origin. Thus, your request for the file will not be sent to GCS but will be made to your proxy which will forward them to GCS. I highly giving PDF.js' FAQ a read, surely it will point you in the right direction.

Related

loading pdf using react-pdf

I am trying to display pdf using react-pdf in create-react-app application.
I followed the instructions but the pdf is not displayed.
import { makeStyles, Box, Grid } from "#material-ui/core";
import React, { useState } from "react";
import Header from "./header";
import contractPdf from "../../sample.pdf";
import { Document, Page } from "react-pdf";
const useStyles = makeStyles((theme) => ({
root: {
padding: "32px 24px 14px 24px",
},
pdfArea: {
borderRight: "1px solid #DDDDDD",
height: "calc(100vh - 195px)",
},
}));
const BasicComponent = (props) => {
const classes = useStyles();
const [numPages, setNumPages] = useState(null);
const [pageNumber, setPageNumber] = useState(1);
function onDocumentLoadSuccess({ numPages: nextNumPages }) {
setNumPages(nextNumPages);
}
return (
<Box className={classes.root}>
<Header />
<Grid container>
<Grid item xs={8}>
<Box className={classes.pdfArea}>
<Document
file={contractPdf}
onLoadSuccess={onDocumentLoadSuccess}
options={options}
>
<Page pageNumber={1} />
</Document>
</Box>
</Grid>
<Grid item xs={4}>
<Box className={classes.inputArea}>User input</Box>
</Grid>
</Grid>
</Box>
);
};
export default BasicComponent;
I checked the debug in development mode and it shows Uncaught SyntaxError: Unexpected token '<' in pdf.worker.js
Can anyone help me?
I appreciate your help. Thank you
I wasted so much time that I decided to write an answer to this question to help anybody in my situation avoid the waste of time. The instructions as described in the github site for react-pdf do not work with react 17.02 CRA 5 and Webpack 5.6.6 regarding the pdf.worker.js worker.
As the site indicates without giving a clear solution,
import { Document, Page } from 'react-pdf/dist/esm/entry.webpack5';
creates a heap out of memory error during compilation that is not fixed even by allocating 8 gigabytes of memory.
Using the standard instructions doesn't work either, creating an error that is dependent of the last web directory that was used in your react-router routes. This creates a weird bug, because sometimes it works and sometimes it doesn't.
The standard instructions say:
that you should add:
import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = 'pdf.worker.min.js';
when using the .min file, instead of the regular .js file, that gave me the idea of adding the following:
import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
But it didn't work either. To make it work I had to do the following:
copy pdf.worker.js and pdf.worker.js.map from pdfjs-dist/legacy/build to public directory (it also works if you copy from the build - not legacy directory)
and,
add to my code the following:
import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = '/pdf.worker.js';
Yes, the '/' did it. Otherwise it'd go back to load my index.html from my /public directory.
As per documentation you have to add this line in your code.(react-pdf)
import { pdfjs } from 'react-pdf';
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

AWS-React: The specified key does not exist

I made one react app. My app works as expected. This app's target is practice AWS-COGNITO. For Cognito validation I am using amazon-cognito-identity-js package. I made one helper function where I validate the Congnito. and reuse it in different component. I split my Nav bar into two components. From Congnito current user I made one callback function and use it in useEffect, and dependencies put the callback function, by default getAuthenticatedUser is null. I add condition where it fetch the data, if getAuthenticatedUser then redirect to signin and signup page. I deployed my app to s3 bucket and this the link. This app runs first time, When I refresh it then got error: 404 Not Found. I really don't know what is the issue and somehow the path react path get disappear. I share my code in code-sandbox.
This is my conditional path
import React from "react";
import SigninLinks from './SigninLinks';
import SignoutLinks from './SignoutLinks';
import useHandlder from '../configHandler/useHandler';
const Nav = () => {
const { getAuthenticatedUser } = useHandlder();
const Links = getAuthenticatedUser() === null ? <SignoutLinks /> : <SigninLinks />
return (
<nav className="nav-wrapper grey darken-3">
<div className="container">
<h2 className="brand-logo">Logo</h2>
{
Links
}
</div>
</nav>
);
};
export default Nav;
This is my handler functions
import React, { useCallback, useEffect } from 'react';
import { CognitoUserPool } from 'amazon-cognito-identity-js';
const Pool_Data = {
UserPoolId: "us-east-1_9gLKIVCjP",
ClientId: "629n5o7ahjrpv6oau9reo669gv"
};
export default function useHandler() {
const userPool = new CognitoUserPool(Pool_Data)
const getAuthenticatedUser = useCallback(() => {
return userPool.getCurrentUser();
},
[],
);
useEffect(() => {
getAuthenticatedUser()
}, [getAuthenticatedUser])
const signOut = () => {
return userPool.getCurrentUser()?.signOut()
}
return {
userPool,
getAuthenticatedUser,
signOut
}
};
It's paths issue. You get 404 on /path not in root /. Check S3 settings for hosting static sites. On S3 make sure static website hosting is enabled:
You react app loads on /index.html JavaScript then redirects and takes over the path. You need S3 to resolve path to index.html, then it will work.

A large number of problems with React, Django, Django REST and Axios

This post is the first part of the following series -
A large number of problems with React, Django, Django REST and Axios
Products on the homepage are not being displayed properly (Django, Django Rest and React)
(React and Django) Displaying products on the homepage is working fine, but when I click on any particular product, then the rendering is wrong
I am going through a very good course about setting up an e-shop, but I have reached the stage, where I am not that much sure, what is the exact purpose of the code, which I have written. (especially the async function in HomeScreen.js) We are using React and Django. My issue is related to the homepage or HomeScreen.js file, which was working fine, when I was loading the products from the static products.json file, but later on, in the course, we had to switch this and load the products from an API using Django REST and Axios (axios was used to remove the CORS error) and my problem now is, that I am not able to load the products to the HomeScreen.js and all I see is a blank page with the header instead of a full page. I am running the react server through the npm start command (the result of that can be seen on the screenshots below) but I also tried to run the Django server, which gives me this error - OSError: [WinError 123]. (Note: the Django server was fixed and is now running - so when I want to display the website, I am running React server and Django server simultaneously)
Please let me know if You can see some solution to these problems. Thank You very much for any help in advance.
The page looks like this -
And it should look like this -
(Note: this problem with displaying of the products was solved by modyfying the urls.py in the base (app) folder -
from django.urls import path
from . import views
urlpatterns = [
path('', views.getRoutes, name="routes"),
path('products/', views.getProducts, name="products"),
path('products/<str:pk>/', views.getProduct, name="product"),
]
was changed to
from django.conf.urls import url
from . import views
urlpatterns = [
url('products/', views.getProducts, name="products"),
url('products/<str:pk>/', views.getProduct, name="product"),
url('routes/', views.getRoutes, name="routes"),
]
)
When I am looking to my console, I am getting a lot of errors such as - (not all of these errors
are harmful, because for example the one relating to the collapseOnSellect was there even in the before all of the other errors have shown up and everything was working fine)
127.0.0.1:8000/api/products/:1 Failed to load resource: net::ERR_CONNECTION_REFUSED
Here are more details about the third error in the console -
(Note: This error has vanished after solving the following (path related and rest related) errors)
Another problem is, that VSCode is giving me these 2 errors - No name 'path' in module 'django.urls' and No name 'include' in module 'django.urls' (these errors are related to the both urls.py files)
(Note: these errors were solved by changing path to url (in both urls.py files) and changing from django.urls import url, include to from django.conf.urls import url, include in the project´s urls.py file and changing from django.urls import url to from django.conf.urls import url in base application´s urls.py file)
and I am getting 2 additional errors in the views.py - Unable to import 'rest_framework.decorators' and Unable to import 'rest_framework.response'. I do not know, why am I getting so many errors, because I am trying to follow every step in the tutorial.
(Note: these two errors were solved in conjuction with this SO post -
Can't import: 'unable to import rest_framework' when importing serializer? (windows))
I am sorry, if my description of the problem is not exact, because I am still just a beginner when it comes to Django and React and so on. But I might explain to You further if You ask me the right questions. I have installed Axios accordingly to the tutorial and I have integrated it into the settings.py file.
Both of the frontend and backend folders are situated in the same folder.
HomeScreen.js -
import React, { useState, useEffect } from "react";
import { Row, Col } from "react-bootstrap";
import Product from "../components/Product";
import axios from "axios"
function HomeScreen() {
const [products, setProducts] = useState([])
useEffect(() => {
async function fetchProducts() {
const { data } = await axios.get('http://127.0.0.1:8000/api/products/')
setProducts(data)
}
fetchProducts()
},[] )
return (
<div>
<h1>Latest Products</h1>
<Row>
{products.map((product) => (
<Col key={product._id} sm={12} md={6} lg={4} xl={3}>
<Product product={product} />
</Col>
))}
</Row>
</div>
);
}
export default HomeScreen;
views.py -
from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .products import products
# Create your views here.
#api_view(['GET'])
def getRoutes(request):
routes = [
'/api/products/',
'/api/products/create/',
'api/products/upload/',
'api/products/<id>/reviews/',
'api/products/top/',
'api/products/<id>/',
'api/products/delete/<id>/',
'api/products/<update>/<id>/',
]
return Response(routes)
#api_view(['GET'])
def getProducts(request):
return Response(products)
#api_view(['GET'])
def getProduct(request, pk):
product = None
for i in products:
if i['_id'] == pk:
product = i
break
return Response(product)
urls.py in the base (app) folder -
from django.urls import path
from . import views
urlpatterns = [
path('', views.getRoutes, name="routes"),
path('products/', views.getProducts, name="products"),
path('products/<str:pk>/', views.getProduct, name="product"),
]
urls.py in the project folder -
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('base.urls')),
]
import React, { useState, useEffect } from "react";
import { Row, Col } from "react-bootstrap";
import Product from "../components/Product";
import axios from "axios"
function HomeScreen() {
const [products, setProducts] = useState([])
useEffect(() => {
async function fetchProducts() {
const responce = await axios.get('http://127.0.0.1:8000/api/products/')
.then((data) => setProducts(data.data)
)}
fetchProducts()
},[] )
return (
<div>
<h1>Latest Products</h1>
<Row>
{products.map((product) => (
<Col key={product._id} sm={12} md={6} lg={4} xl={3}>
<Product product={product} />
</Col>
))}
</Row>
</div>
);
}
export default HomeScreen;

Loading gltf in gatsby site with react-three-fiber

I've been trying to load a GLTF model into my gatsby site using react-three-fiber, but can't seem to get it to load. This seems like it should be very simple, but I'm new to Gatsby and threejs and was wondering if I could get some guidance.
My model is stored as static/models/crerar.glb, and I used gltfjsx to generate a Model component. I've tried referencing just 'models/crerar.glb' but haven't had luck either.
In index.js, I have:
import Layout from "../components/layout"
import SEO from "../components/seo"
import React, { Suspense, useRef, useState } from "react"
import { Canvas, useFrame, useLoader } from "react-three-fiber"
import Model from "../components/Crerar"
const IndexPage = () => (
<Layout>
<Canvas>
<ambientLight intensity={0.2} />
<Model />
</Canvas>
</Layout>
)
export default IndexPage
and in Crerar.js (stored in components)
/*
auto-generated by: https://github.com/react-spring/gltfjsx
*/
import * as THREE from 'three'
import React, { useRef } from 'react'
import { useLoader } from 'react-three-fiber'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
export default function Model(props) {
const group = useRef()
const { nodes, materials } = useLoader(GLTFLoader, '../static/models/crerar.glb')
return (
<group ref={group} {...props} dispose={null}>
<mesh material={nodes.mesh_0.material} geometry={nodes.mesh_0.geometry} />
</group>
)
}
the path is wrong. the json.parse error you're getting is because the loader tries to parse a HTML 404 fetch-error as a GLTF. you can make sure by opening dev tools and the networking tab. you should see it's trying to reach your file, but can't.
if the model is within your src folder you have to import it first, then use the hashed url that you get. this is my recommendation, don't mess around with public files, always import your stuff. it's safer, the compiler will complain if the file isn't present, and it's better for cache control.
otherwise, if the file is inside /public or i guess it's /static in gatsby (?) then the url has to be something like "/file.glb". sometimes it's /public/file.glb or /static/file.glb, it depends on your bundling environment (you can try fetching the file via the browsers url bar, if an url works, that's the one you should pass on to the loader).
if your file is draco compressed, then draco must also be inside public or static. see: https://codesandbox.io/s/r3f-ibl-envmap-simple-y541h
you can safely use useLoader(GLTFLoader, url), it's just a wrapper around new GLTFLoader().load(url, data => ...) + suspense. It's not experimental any longer, even though it may have that warning on Github.
gatsby copies everything from static into the public folder, so change your url to:
const { nodes, materials } = useLoader(GLTFLoader, '/models/crerar.glb')

React Apollo Error: Invariant Violation: Could not find "client" in the context or passed in as an option

I'm building a project using React, Apollo and Next.js. I'm trying to update react-apollo to 3.1.3 and I'm now getting the following error when viewing the site.
Invariant Violation: Could not find "client" in the context or passed in as an option. Wrap the root component in an , or pass an ApolloClient instance in via options.
If I downgrade the react-apollo package to 2.5.8 it works without issue so I'm thinking something has changed between 2.5 and 3.x but can't find anything in the react-apollo or next-with-apollo documentation to indicate what that might be. Any assistance would be greatly appreciated.
withData.js
import withApollo from 'next-with-apollo';
import ApolloClient from 'apollo-boost';
import { endpoint } from '../config';
function createClient({ headers }) {
return new ApolloClient({
uri: endpoint,
request: operation => {
operation.setContext({
fetchOptions: {
credentials: 'include'
},
headers
});
},
// local data
clientState: {
resolvers: {
Mutation: {}
},
defaults: {}
}
});
}
export default withApollo(createClient);
_app.js
import App from 'next/app';
import { ApolloProvider } from 'react-apollo';
import Page from '../components/Page';
import { Overlay } from '../components/styles/Overlay';
import withData from '../lib/withData';
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
// this exposes the query to the user
pageProps.query = ctx.query;
return { pageProps };
}
render() {
const { Component, apollo, pageProps } = this.props;
return (
<ApolloProvider client={apollo}>
<Overlay id="page-overlay" />
<Page>
<Component {...pageProps} />
</Page>
</ApolloProvider>
);
}
}
export default withData(MyApp);
In my case, I found that I had react-apollo#3.0.1 installed as well as #apollo/react-hooks#3.0.0. Removing #apollo/react-hooks and just relying on react-apollo fixed the invariant issue for me. Make sure that you aren't using any mismatched versions in your lock file or package.json
This is what someone said in a GitHub issue thread, which, was the case for me too. Make sure you try it!
I've had a mixture of solutions, i think it does boil down to how you initially go about setting up all the related packages.
"Some packages don't work well with others when it comes to connecting the client to Reacts Context.Provider"
I've had two go two fixes that seem to work well (With new projects and updating old):
1: Uninstall #apollo/react-hooks
Then:
import { ApolloProvider } from "#apollo/client";
instead of:
import { ApolloProvider } from "react-apollo";
(This allowed me to keep the "#apollo/react-hooks" package without conflicts)
3: Double-check that the server that is serving HttpLink client URI is up and running for the client to connect (This give a different error then the one were talking about but is still good to know in this situation)
Conclusion: It can be a slight bit of trial and error, but try to use the matching/pairing packages
I uninstalled 'react-apollo', used '#apollo/client' instead, it solved the issue for me.
import gql from 'graphql-tag';
import {graphql} from '#apollo/react-hoc';
import { ApolloClient, InMemoryCache } from '#apollo/client';
import { ApolloProvider } from '#apollo/react-hooks';
These imports worked for me perfectly. I had a great time debugging and finding different import libraries but finally after 3 hours this was the solution for using graphql and appolo.
I found this to be the solution as well, though now I'm only using #apollo/client and apollo-link since they are the latest version.
import {ApolloProvider} from 'apollo/client' instead 'react-apollo'or '#apollo/react-hooks'

Resources