fetch request not working with headers - reactjs

I am working on login page with ReactJs,Spring Boot and rest web services.My Reactjs frontend application is running on port 8080 while my webservice/spring boot application is running on port 9090. I am trying to use the "fetch" method to connect with my backend code, but I am facing error while passing headers in fetch request. If I remove headers property, execution goes into the called backend method. I need to pass Headers in fetch method as it required to access them in web service method.
Please find Snapshot of network requests and responses. Without Headers With headers
Below is my code of React JSX file:
import React, { Component } from 'react';
class App extends Component {
constructor(props){
super(props);
this.state={
email:'',
password:''
}
this.handleClick = this.handleClick.bind(this);
}
handleClick(){
var usernameFieldValue = this.refs.emailField.value;
var passwordFieldValue = this.refs.passwordField.value;
this.setState({email:usernameFieldValue})
this.setState({password:passwordFieldValue})
//var headers = 'Basic bmltZXNoLnBhdGVsQHRhdHZhc29mdC5jb206cGFzc3dvcmQ=';
//alert(headers);
fetch('http://192.168.0.239:9090/ws/login',{
mode: 'cors',
method: 'get',
headers: {
"Content-Type": "application/json",
"Authorization": "Basic bmltZXNoLnBhdGVsQHRhdHZhc29mdC5jb206cGFzc3dvcmQ="
}
}).then((response) => response.json())
.then((responseJson) => {
alert(" responseJson : " + responseJson);
})
.catch((error) => {
alert("Error : " +error);
});
}
render() {
return (
<div id="loginFrame">
<div className="container">
<div id="loginHeader" className="row">
<div className="col-xs-12 text-center">
<img src="" alt="'Logo" />
</div>
</div>
<div id="loginBody" className="row">
<div className="col-xs-6 col-xs-offset-3">
<div className="center-block">
<div id="login-panel">
<form id="loginForm" className="form-horizontal" role="form">
<div className="form-group">
<input type="text" className="form-control input-lg" id="email" name="email" ref="emailField" placeholder="Email address"/>
</div>
<div className="form-group">
<input type="password" className="form-control input-lg" id="password" name="password" ref="passwordField" placeholder="Password"/>
</div>
<div className="form-group">
<button onClick={this.handleClick} className="btn btn-lg btn-success pull-right">Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;

var url = "https://yourUrl";
var bearer = 'Bearer '+ bearer_token;
fetch(url, {
method: 'GET',
withCredentials: true,
credentials: 'include',
headers: {
'Authorization': bearer,
'X-FP-API-KEY': 'iphone',
'Content-Type': 'application/json'}
}).then((responseJson) => {
var items = JSON.parse(responseJson._bodyInit);
})
.catch(error => this.setState({
isLoading: false,
message: 'Something bad happened ' + error
}));

You don't need mode: cors, this is default.
const headers = new Headers({
"Content-Type": "application/json",
"Authorization": "Basic bmltZXNoLnBhdGVsQHRhdHZhc29mdC5jb206cGFzc3dvcmQ="
});
fetch('http://192.168.0.239:9090/ws/login', {
method: 'GET',
headers,
}).then().then().catch();

Based on your comments, it sounds like the underlying problem is that you're doing a CORS request from your react app, which is being served from a different server than your spring backend. I don't know Spring, but adding a Access-Control-Allow-Origin HTTP header (as well as some other CORS related headers) will clear up the problem. I'm not 100% sure why when you fetch with no headers, it works. There may be a deeper configuration issue or you need to configure it to allow requests with those headers you're passing (Access-Control-Allow-Headers). Note that if you don't plan to allow cross-origin requests in production you may want to add those headers except when in development.
You can also fetch in no CORS mode (pass {mode: 'no-cors'}), but there's a lot of limitations to that and I doubt that's what you want.

Related

image file isnt being read by react

I am using formData to send details to my backend but somehow my image path isn't being sent.
Post photo
<div className="form-group">
<label className="btn btn-block btn-success">
<input
onChange={handleChange("photo")}
ref={inputRef}
type="file"
name="photo"
accept="image"
placeholder="choose a file"
/>
</label>
</div>
this is the form i am using
Handle change and submit button
const onSubmit = (event) => {
event.preventDefault();
setValues({...values,error:"",loading:true});
createProduct(user._id,token,JSON.stringify(values))
.then(data=>{
if(data.error){
setValues({...values,error:data.error});
}else{
setValues({...values,
name:"",
description:"",
price:"",
photo:"",
stock:"",
createdProduct:data.name,
loading:false});
}
}).then(response=>{
})
.catch(err=>console.log(err));
//
};
const handleChange = name => event => {
const value=name==="photo"?event.target.files[0]:event.target.value;
formData.append(name,value)
setValues({...values,[name]:value});
//
};
And this is the api call to backend
export const createProduct=(userId,token,product)=>{
console.log(product)
return fetch(`${API}/product/create/${userId}`,{
method: "POST",
headers:{
Accept: "application/json",
Authorization: `Bearer ${token}`
},body:product
})
.then(response=>{
return response.json();
})
.catch(err=>console.log(err));
}
The api is working fine with postman , I am using formidable in backend. Some answers from stack made the path of the file have c:\fakepath and so m too confused what to do .
Thanks for help.

Unable to send a photo from React Native to Cloudinary

I'm trying to upload images to Cloudinary from my React Native app, but I'm getting the "400 Bad Request" saying the image I'm sending is ""x-cld-error": "Unsupported source URL".
ImageUpload.js
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1
})
if (!result.cancelled) {
setImageSource(result.uri);
}
}
I'm currently using the ImagePicker from expo-image-picker. I'm taking the imageSource I've obtained from above and appending it to data before sending it to Cloudinary. The result.uri shows the URL of the picture from the iOS simulator.
CreatePost.js
const uploadFile = async () => {
const data = new FormData();
data.append('file', imageSource);
data.append('upload_preset', 'test_folder')
const res = await fetch('https://api.cloudinary.com/v1_1/{my_cloudinary}/image/upload', {
method: 'POST',
body: data,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
})
const file = await res.json()
setImage(file.secure_url)
setLargeImage(file.eager[0].secure_url)
}
When I console.log res, it shows that the status is 400.
You can try using ajax. For example here:
<h1>Upload to Cloudinary with FormData</h1>
<div>
<p>
Set your cloud name in the API URL in the code: "https://api.cloudinary.com/v1_1/<strong><cloud name></strong>/image/upload" before running the example.
</p>
</div>
<form action="" method="post" enctype="multipart/form-data" onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Upload example</legend>
<p>
<label for="upload_preset">Unsigned upload Preset: <input type="text" name="upload_preset">(set it here)</label>
</p>
<p>
<label >Select your photo:
<input type="file" name="file"></label>
</p>
<p>
<input type="submit" value="Submit" />
</p>
<img id="uploaded">
<div id="results"></div>
</fieldset>
</form>
enter code here https://jsfiddle.net/shirlymanor/s1hou7zr/

401 ERROR with API sending blank basic auth

I am creating an API to send a basic auth login request to my flask backend, however when sending a request I get
{username: "ww", password: "ww"}
POST http://localhost:5000/login 401 (UNAUTHORIZED)
i have logged the data entered to check is was being set, this response is returned via the js console on the browser, the logging in my flask console is as follows :
127.0.0.1 - - [10/Nov/2019 16:21:07] "OPTIONS /login HTTP/1.1" 200 -
{'username': '', 'password': ''}
127.0.0.1 - - [10/Nov/2019 16:21:07] "POST /login HTTP/1.1" 401 -
My flask login route looks like
#app.route('/login', methods =['POST'])
def login():
if request.method == 'POST':
auth = request.authorization
print(auth)
if not auth.username or not auth.password:
return make_response('Could not verify :(', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'})
user = User.query.filter_by(username = auth.username).first()
if not user:
return make_response('Could not verify', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'})
if check_password_hash(user.password, auth.password):
token = jwt.encode({'public_id' : user.public_id, 'exp' : datetime.datetime.utcnow() + datetime.timedelta(minutes=30) }, app.config['SECRET_KEY'])
return jsonify({'token' : token.decode('UTF-8')})
return make_response('Could not verify', 401, {'WWW-Authenticate' : 'Basic realm="Login Required"'})
this is the login component on my react front end
export class Login extends React.Component {
constructor(props){
super(props);
this.state = {
username: '',
password: '',
}
}
changeHandler = e => {
this.setState({[e.target.name]: e.target.value})
}
submitHandler = e => {
const headers = {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
}
var username = this.username
var password = this.password
e.preventDefault()
console.log(this.state)
axois.post('http://localhost:5000/login',this.state,{
headers: {
headers
}
,auth: {
username : username,
password: password
}
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
}
render() {
const {username, password} = this.state
return <div className = "base-container" ref={this.props.containerRef}>
<div className="content">
<div className="logo">
<img src={Logo} alt="Logo"/>
</div>
<form className="form" onSubmit={this.submitHandler}>
<div className="form-group">
<label htmlFor="username"> Username</label>
<input type="text"
name="username"
value ={username}
placeholder="Username"
onChange={this.changeHandler}/>
</div>
<div className="form-group">
<label htmlFor="password"> Password</label>
<input type="password"
name="password"
value={password}
placeholder="Password"
onChange ={this.changeHandler}/>
</div>
<button type="submit" className="btn">Login</button>
</form>
</div>
<div className="footer">
</div>
</div>
}
}
My request works through using postman so im unsure why it doesnt using React? I am using Flask-Cors to prevent CORS errors and storing the user data in auth header so im not sure why flask cant read it.
I am very new to this so any help would be great :) Thanks !

How to send a fetch post request from react component to backend

I want to send the fetch post request to the server from react class component. I never did fetch post. So how can I do this from that component using thunk.
class Add extends Component {
constructor(props) {
super(props);
this.state = {username: '', email:'', text:''};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({value: event.target.value});
}
handleSubmit(event) {
alert (JSON.stringify(this.state))
event.preventDefault();
}
render(){
return (
<div className="addcontainer">
<div style={{display: 'flex', justifyContent: 'center'}}>
<h4>Add new task here:</h4>
</div>
<form onSubmit={this.handleSubmit}>
<div className="wrapper">
<label for="username"><b>Username</b></label>
<input type="text" value={this.state.username} onChange={e => this.setState({ username: e.target.value })} placeholder="Enter Username" name="uname" required />
<label for="email"><b>Email</b></label>
<input type="text" value={this.state.password} onChange={e => this.setState({ email: e.target.value })} placeholder="Enter Email" name="email" required />
<label for="text"><b>Text</b></label>
<input type="text" value={this.state.password} onChange={e => this.setState({ text: e.target.value })} placeholder="Enter Task" name="text" required />
<button className="login" type="submit">Add task</button>
</div>
</form>
</div>
)
}
}
I also have an example of the jquery ajax request in documentation, but it is of little help to me. Please help me to write thunk with fetch
$(document).ready(function() {
var form = new FormData();
form.append("username", "Example");
form.append("email", "example#example.com");
form.append("text", "Some text");
$.ajax({
url: 'https://uxcandy.com/~shapoval/test-task-backend/create?developer=Example',
crossDomain: true,
method: 'POST',
mimeType: "multipart/form-data",
contentType: false,
processData: false,
data: form,
dataType: "json",
success: function(data) {
console.log(data);
}
});
});
Here is thunk that works with fetch get:
const getRepos = username => async dispatch => {
try {
var url = `https://uxcandy.com/~shapoval/test-task-backend/?developer=sait&sort_field=${username}`;
const response = await fetch(url);
const responseBody = await response.json();
//console.log(responseBody.message.tasks);
dispatch(addRepos(responseBody.message.tasks));
} catch (error) {
console.error(error);
dispatch(clearRepos());
}
};
You can use second argument of fetch function to add options e.g.
fetch(url, {
method: "POST", // *GET, POST, PUT, DELETE, etc.
mode: "cors", // no-cors, cors, *same-origin
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
credentials: "same-origin", // include, *same-origin, omit
headers: {
"Content-Type": "application/json",
// "Content-Type": "application/x-www-form-urlencoded",
},
redirect: "follow", // manual, *follow, error
referrer: "no-referrer", // no-referrer, *client
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
For more information please refer here
other effective way to make api hit is by using axios

ReactJS How To Set Cookie From Fetch Request to Back End

I have a react front end that is talking to a Node Back End. I am able to make requests and such . However, I noticed that I cannot set the cookie that I am getting back. My back end will respond upon logging in, with a message and a cookie. How should I be doing this?
Relevant code:
import React from "react";
import Fetch from 'react-fetch';
export class Loginform extends React.Component{
constructor(){
super();
this.state = {message : ""};
this.state = {cookie : ""};
}
Login(e){
e.preventDefault();
var Email_Address = this.refs.Email.value;
var Password = this.refs.Password.value;
fetch("http://localhost:5000/api/form", {
method: "POST",
headers: {
"Content-Type":"application/json",
"Accept":"application/json"
},credentials: "include",
body: JSON.stringify({
Email_Address: Email_Address,
Password: Password
})
}).then(response=>response.json())
.then(response => this.setState({message: response.Message, cookie :response['x-access-token']}));
}
render(){
return(
<div className="LoginContainer">
<form name="Loginform" method="post" action="http://localhost:5000/api/tavern" onSubmit={this.Login.bind(this)}>
<div className="block">
<label><i className="fa fa-envelope"></i></label>
<input ref="Email" type="email" placeholder="E-Mail" required title="Enter Valid E-Mail Address"/>
<i className="fa fa-check" aria-hidden="true"></i>
</div>
<div className="block">
<label><i className="fa fa-lock"></i></label>
<input ref="Password" type="password" placeholder="Enter Your Password" pattern=".{9,}" required title="9 Characters Minimum"/>
<i className="fa fa-check" aria-hidden="true"></i>
</div>
<div className="returnmessage"> {this.state.message}</div>
<div className="buttons"> <button type="submit" value="Submit">Login</button></div>
</form>
</div>
);
}
}
I had to add this to make the answer below applicable :
npm install react-cookies --save
import cookie from 'react-cookies'
Here is my code after.
fetch("http://localhost:5000/api/tavern", {
method: "POST",
headers: {
"Content-Type":"application/json",
"Accept":"application/json"
},credentials: "include",
body: JSON.stringify({
Email_Address: Email_Address,
Password: Password
})
}).then(response=>response.json())
.then(function (data){
console.log(data);
cookie.save('x-access-token', data['x-access-token']);
this.setState({message: data.Message, cookie :data['x-access-token']})
}.bind(this)
)
}
What you are doing is not setting the cookie. You are just creating a variable in state called cookie.
Install this package.
The correct syntax is
Cookies.set('access_token', response.headers['x-access-token'])
Now it is actually stored in to your browser cookies. You can go ahead and access it back using
Cookies.get('access_token')
For react you can also use react-cookie package. And if the React version >16.8.0 you can use React Hooks.
import { useCookies } from 'react-cookie';
const [cookies, setCookie] = useCookies(['name']); // getting react hooks
cookie2.set('access_token', 'content of cookie');
cookie = cookies.get('access_token');
console.log(cookie)

Resources