Getting a 403 error while using Axios in React - reactjs

Hey great people of StackOverflow,
I'm creating a React app that uses the Google API, and I'm getting a 403 error when I use the search tool I've built, here's the following code:
import axios from 'axios';
const KEY = 'API KEY';
export default axios.create({
baseURL: 'http://www.googleapis.com/youtube/v3',
params: {
part: 'snippet',
maxResults: 5,
key: KEY
}
});
That's the API component to my React project, in my App.js, the callbacks look like this:
import React from 'react';
import SearchBar from './SearchBar';
import youtube from '../apis/youtube';
class App extends React.Component {
onTermSubmit = (term) => {
youtube.get('/search', {
params: {
q: term
}
});
};
I thought it might have been one of the EventHandlers not going through with "submit" but that wasn't the case as I was able to look at the Dev Console and I isolated XHR requests in the Network, and this is what I got:
Request URL: http://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=5&key=MYAPIKEY
Request Method: GET
Status Code: 403 Forbidden
Any help would be greatly appreciated, thank you folks in advance.

friend!)
Yes, you're absolutely right — "submit" EventHandlers are okay as well as your app logic!
But for search-request we shouldn't use API KEY because everyone (even unauthorized user) can just search something in Google, cannot he? :)
So, in this term, you should remove the key property in your request:
import axios from 'axios';
const KEY = 'API KEY';
export default axios.create({
baseURL: 'http://www.googleapis.com/youtube/v3',
params: {
part: 'snippet',
maxResults: 5
}
});
That's all, my friend!) Good luck to you!

Related

React Hook "useAuth0" cannot be called at the top level

I'm trying to implement Auth0 into my React project using this tutorial: https://auth0.com/docs/quickstart/spa/react/02-calling-an-api.
Since I don't want to pass the access token on every page, I'm using a global file which I try to use on every Axios API call.
Code (api.js):
import axios from 'axios';
import { useAuth0 } from '#auth0/auth0-react';
const {getAccessTokenSilently} = useAuth0();
const token = await getAccessTokenSilently();
export default axios.create({
baseURL: `http://localhost:8080/`,
headers: {Authorization: `Bearer ${token}`},
timeout: 2000
});
I receive the following error:
Line 4:34: React Hook "useAuth0" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
Example call in 'AssignmentSlice.js' (using Redux):
api.post(`assignment/add`, initialAssignment)
.then(res => {
console.log(res.data);
return res.data;
}).catch(err => {
console.log(err.response);
return err.response;
})
What would be the best way/pattern to implement the Auth0 access token?
This mean you need to call useAuth0 from react component to get token. Then passing token to API layer and call API as normal
See example here: https://auth0.github.io/auth0-react/

How to integrate AngularJs with Django

I have little/no knowdlege in AngularJs, i want to create a very simple SPA with django as backend and AngularJs as frontend. User will be able to Register, Login & logout all taking place on the same page when a user logs in they will see a message"Welcome (user email)".
This is very easy to do in a normal django web app as we don't even need to create the whole authentication system. But i want to learn how to do this with AngularJS as my employer wants me to do.
I have read the basics of AngularJs and it looked well explained (it made sense) but how to integrate it with django. I tried searching on the internet but there is nothing out there, the tutorials that are there are more then 7 years old.
First you need to look at angular HttpClient because that what going to enable communication between django and angular..then create a service to handle authentication you can call it anything import HttpClient inside to login user for example i will do this:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { Router } from '#angular/router';
#Injectable({
providedIn: 'root'
})
export class AuthServiceService {
constructor(private http: HttpClient, private router: Router) { }
// Skip authorization from these requests
private skip_token_headers = {
skip: "true"
};
loginUser(user): Observable<any> {
return this.makePostRequest(environment.LOGIN_URL, user,
this.skip_token_headers);
}
makePostRequest(url: string, data: any, req_headers: any): Observable<any> {
return this.http.post(url, data, { headers: req_headers });
}
then in your login component under .ts you import your service and use it like bellow
onLoginSuccess(result){
localStorage.setItem('token', result.key);
localStorage.setItem('user', JSON.stringify(result.user));
this.router.navigate(['/userpage']);
}
onSubmit(form: NgForm) {
this.authService.loginUser(this.user).subscribe(
result => {
this.onLoginSuccess(result);
},
error => {
this.login_errors = [];
if (error['error']['non_field_errors']) {
this.login_errors = error['error']['non_field_errors'];
}
// this.clearErrors(this.user);
// this.showErrors(error);
}
);
}

Use ApolloClient in Gatsby with localhost / local IP uri

I am trying to use ApolloClient with a local IP as uri, but when I set it, it automatically changes it from http to https and, of course, it doesn't work locally.
I've tried 2 way of configuring Gatsby to use ApolloClient.
The first way is in gatsby-browser like so:
import React from 'react';
import 'core-js/modules/es6.set';
import 'core-js/modules/es6.map';
import 'raf/polyfill';
import Apollo from 'providers/Apollo';
export const wrapRootElement = ({ element }) => <Apollo>{element}</Apollo>;
And, the ApolloClient config:
import React from 'react';
import { ApolloProvider, ApolloClient, InMemoryCache } from '#apollo/client';
export default ({ children }) => {
const client = new ApolloClient({
uri: 'http://192.162.1.112:4000/graphql',
cache: new InMemoryCache(),
request: async operation => {
...
},
fetchOptions: {
mode: 'no-cors',
},
});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
The second way is using the plugin gatsby-plugin-apollo in gatsby-config like so
{
resolve: 'gatsby-plugin-apollo',
options: {
uri: 'http://192.168.1.112:4000/graphql'
}
}
Notice both uri have http.
Also, it is either one or the other, not both. (Although I've tried with both and it the same result).
This is what I get trying to do a gql query in the network tab:
It is enforcing https and I can't test locally. How do can I make request to http using Gatsby and ApolloClient?
By the way, I set ApolloClient just like this in another project that doesn't use Gatsby (obviously not using the gatsby plugin either) and it works as expected.
There are a few confusing things in the way you are using apollo client.
There is no point in explaining something that has already been done.
You might want to check out this talk and demo by Jason Lengstorf. Here he explained how one can get started with gatsby + apollo client.
Youtube
gatsby-with-apollo

Firebase: .default is not a constructor

I am trying to follow this tutorial.
I'm currently stuck at the step which introduces react context to firebase.
This code block is the source of the current problem:
import Firebase, { FirebaseContext } from './components/firebase';
ReactDOM.render(
<FirebaseContext.Provider value={new Firebase()}>
<App />
</FirebaseContext.Provider>,
document.getElementById('root'),
);
serviceWorker.unregister();
When I try this, I get an error that says:
TypeError:_components_firebase__WEBPACK_IMPORTED_MODULE_5__.default is not a constructor
I have seen this post, which relates to Vue but says that the cause of an error with .default is not a constructor (not the rest of it), is because Firebase object should not be called with new keyword.
I tried removing new, but that generates an error message that says:
TypeError: Object(...) is not a function
I'm wondering if this has anything to do with the unusual way that the tutorial configures the app for firebase - which is with a class that uses a constructor (still don't understand why this is done this way):
class Firebase {
constructor() {
app.initializeApp(config);
this.auth = app.auth();
this.db = app.database();
}
export default Firebase;
Does anyone using Firebase with React know how to use the context API and if you do, have you found a way around this problem?
The firebase config setup files are:
index:
import FirebaseContext, { withFirebase } from './Context';
import Firebase from '../../firebase.1';
export default Firebase;
export { FirebaseContext, withFirebase };
context:
import React from 'react';
const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
<FirebaseContext.Consumer>
{firebase => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default FirebaseContext;
NEXT ATTEMPT
I found this post, which looks like it might have been trying to follow the same tutorial.
That approach requires that I add back the auth method in the firebase.1.js config file so that it now looks like this:
class Firebase {
constructor() {
app.initializeApp(config).firestore();
this.auth = app.auth();
// this.db = app.database();
// this.db = app.firebase.database()
this.db = app.firestore();
}
doCreateUserWithEmailAndPassword = (email, password) =>
this.auth.createUserWithEmailAndPassword(email, password);
}
Then, the submit handler in the form is like this:
handleCreate = values => {
values.preventDefault();
const { name, email, password } = this.state;
Firebase
.doCreateUserWithEmailAndPassword = (email, password) => {
return this.auth
.createUserWithEmailAndPassword(email, password)
.then((res) => {
Firebase.firestore().collection("users").doc(res.user.uid).set({
email: values.email,
name: values.name,
role: values.role,
createdAt: Firebase.FieldValue.serverTimestamp()
}).then(() => this.history.push(ROUTES.DASHBOARD));
})
.catch(err => {
console.log(err.message);
});
};
};
When I try this, I don't get any errors, but the form does not submit - it just hangs.
NEXT ATTEMPT
Since the FirebaseContext.Consumer includes a line with firebase in lowercase, I tried all of the same steps above, but replacing title case Firebase with lower case firebase. I also tried this.firebase (I don't know why) and this.props.firebase (I have seen other posts try that but still don't know why).
None of these approaches work either.
When I try to console.log(Firebase) above the FirebaseContext.Provider, I get this a big log with lots of drop down menus that starts with this:
FirebaseAppImpl {firebase_: {…}, isDeleted_: false, services_: {…},
tokenListeners_: Array(0), analyticsEventRequests_: Array(0), …}
INTERNAL: {analytics: {…}, getUid: ƒ, getToken: ƒ,
addAuthTokenListener: ƒ, removeAuthTokenListener: ƒ}
One of the drop down menus inside this log is labelled "options_" and includes my firebase app credentials.
I think this could be related to the problem in my recent other answer.
I managed to get new Firebase working by simplifying the import/export setup.
In the react app the imports are now:
import { FirebaseContext } from './components/context';
import Firebase from './components/firebase';
Those imports and the new work after I replaced the complicated "import and re-export" code in the components/firebase.js with simply the definition for the class Firebase from the tutorial.
After this another error Firebase: Firebase App named '[DEFAULT]' already exists (app/duplicate-app). pops up, but that could be because I didn't follow the whole tutorial and some configuration is missing.
Replicating everything you are dealing with is quite difficult without having the full source of your project.
Here is the test App.js I used after the npx create-react-app react-firebase-authentication and after installing firebase.
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { FirebaseContext } from './components/context';
import Firebase from './components/firebase';
function App() {
const foo = new Firebase()
return (
<div className="App">
... omitted ...
</div>
);
}
export default App;

Mock api calls from Storybook

Does axios-mock-adapter only work on requests made with axios?
I have written a component that POSTs to an API (using vanilla XHR, not axios). I'm testing it in Storybook and want to intercept those POST requests since the endpoint doesn't exist yet:
import React from "react"
import { storiesOf } from "#kadira/storybook"
import MyComponent from "./MyComponent"
import axios from "axios"
import MockAdapter from "axios-mock-adapter"
var mock = new MockAdapter(axios)
storiesOf("My Component", module).addWithInfo(
"Simulator",
() => {
mock.onPost().reply(500)
return <MyComponent />
},
{}
)
My component still is trying to hit the API endpoint and I am getting a 404 response - not the expected 500 response.
Does axios-mock-adapter only work on requests made with axios?
Does the mock call have to be inside MyComponent?
Thanks.
xhr-mock should work for local testing where you probably don't want to make requests across the internet.
Outside of testing, if you are waiting on the real endpoints to be built you could use Mock/it (https://mockit.io) in development. You can claim your own dedicated subdomain and swap it out later for the real one. Disclaimer: this is a side project I recently released and would love any feedback on it!
You can use xhr-mock instead of axios-mock-adapter.
Utility for mocking XMLHttpRequest.
Great for testing. Great for prototyping while your backend is still being built.
Works in NodeJS and in the browser. Is compatible with Axios, jQuery, Superagent >and probably every other library built on XMLHttpRequest
import mock from 'xhr-mock';
storiesOf("My Component", module).addWithInfo("Simulator",
() => {
mock.post('', {
status: 500,
body: '{}'
});
return <MyComponent />
},
{}
)
Additionaly you need to add jquery script in preview-head.html file in storybook
1) https://www.npmjs.com/package/xhr-mock
I've started using json-server to intercept API calls. You have to start it in one tab, and start storybook in another, but it is pretty cool.
You can use fetchMock npm module. All XHR call will be mocked with data you provide.
Storybook configuration:
import React from 'react';
import Messages from '../components/messagesList';
import fetchMock from "fetch-mock";
import MESSAGES from './data/messages';
fetchMock.get('/messages', MESSAGES);
export default {
title: 'Messages',
component: Messages
};
export const ToStorybook = () => <Messages />;
ToStorybook.story = {
name: 'Messages list',
};
The complete tutorial how to do it is on YouTube
You can use storybook-addon-mock to mock any fetch or XHR request using the addon panel.
This package supports
Modify response from the panel and test on the fly.
Modify the status code to verify the error response.
Add a delay time to experience the loading state.

Resources