How do I combine both environments for Relay Modern? - javascript

There's an example of injecting NetworkLayer with middlewares on the client side for Relay Modern that includes the following lines:
const network = new RelayNetworkLayer([...])
On the other hand, my current setup were taken from here and include the following:
function fetchQuery(
operation,
variables
) {
return fetch('/graphql', {
method: 'POST',
credentials: 'same-origin', // 启用 cookie
headers: {
'Content-Type': 'application/json',
}, // Add authentication and other headers here
body: JSON.stringify({
query: operation.text, // GraphQL text from input
variables,
}),
}).then(response => {
return response.json()
})
}
const network = Network.create(fetchQuery)
How can I combine both into a single object network (is there a special constructor or something like that)?
I'd like to have a support for both middlewares and the query as well.

Just use react-relay-network-modern
This should work same as your fetchQuery function:
import { urlMiddleware, RelayNetworkLayer } from 'react-relay-network-modern'
const network = new RelayNetworkLayer([
urlMiddleWare({
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
}
})
])

Related

Creating tickets using Zendesk api with React

I working on intergrating a react app with the zendesk api for creating support tickets.
Till now i have completed the form flow, but when i making the request to the zendesk api i am getting 401.
I am using the api_key approach for this.
I am fairly new to zendesk, if anyone can help me regarding that.
Here is my code after user clicks submit.
const onSubmit = async () => {
try {
console.log('setInfo', info)
const data = { request: { subject: 'test', comment: { body: 'testdesc' } } }
const user = 'test#test.com'
const api_token = 'some_api_key'
const url = 'https://url.zendesk.com/api/v2/tickets.json'
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'no-cors',
headers: {
'Content-Type': 'application/json',
Authorization: api_token,
// 'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(data), // body data type must match "Content-Type" header
})
console.log('respone', response)
} catch (error) {
console.log('respone error', error)
}
}
It looks like you're not sending the right authorization header. According to Zendesk API reference you need to use the following format for the credentials:
{email_address}/token:{api_token}
Example:
jdoe#example.com/token:6wiIBWbGkBMo1mRDMuVwkw1EPsNkeUj95PIz2akv
After base64-encoding the resulting string, add it to the Authorization header as follows:
Authorization: Basic amRvZUBleGFtcGxlLmNvbS90b2tlbjo2d2lJQldiR2tCTW8xbVJETXVWd2t3MUVQc05rZVVqOTVQSXoyYWt2

how do i use a jwt token?

im new to this and spent all my time trying to figure out how to build a way to generate jwt tokens - given the understanding that you need them for user 'signed in' status.
i used fastapi, and when i login/register using my app, i now get a token, and 'bearer':
{access_token: 'super long string', token_type: 'bearer'}
how do i use this to show another view/page/component? what is the process? is there some sort of decoder? all the videos/tutorials i see are focused on how to get it using node or other means, but i already have it...
You will have to pass this token in your headers in order to access the API.
Consider the following Axios js example:
var axios = require('axios');
var config = {
method: 'get',
url: `http://${<your_api_url>}/v1/users/`,
headers: {
'Authorization': `${<token_type>} ${<access_token>}`
}
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
This is what I did:
Step 1 - set the state for my parent page:
const [jwtholder, setJwtHolder] = useState('non-bearer')
const [jwttoken, setJwtToken] = useState('');
const mainprops = {
// session,
jwtholder,
setJwtHolder,
jwttoken,
setJwtToken,
visitorType,
setVisitorType
};
Step 2 - adjust the conditional rendering in the parent page, and pass the states:
else if (jwtholder=='bearer' && visitorType =='buyside') {
return(
<div>
<Buyside {...mainprops}/>
</div>
)}
else if (jwtholder=='bearer' && visitorType =='sellside') {
return(
<div>
<Sellside {...mainprops}/>
</div>
)}
};
Step 3 - pass those main props through the formik component:
onSubmit={ (values, {setSubmitting, resetForm} ) => {
setTimeout(() => {
_handleLogin({mainprops, values});
resetForm();
setSubmitting(false);
}, 1000)
}}
Step 4 - use the handler to pass the request, and adjust the parent state:
export default async function _handleSubmit(mainprops,creds) {
if (creds.api == 'register'){
var publish_api = 'http://localhost:8007/register/'; //fastapi
}
else if (creds.api =='login') {publish_api = 'http://localhost:8007/login/';}//fastapi
const requestOptions = {
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',
},
body: JSON.stringify(creds.Data)
};
//wait for the promise to come back:
let response = await fetch(publish_api, requestOptions);
let authorization = await response.json()
mainprops.setJwtHolder(authorization.token_type);
mainprops.setJwtToken(authorization.access_token);
mainprops.setVisitorType('buyside')
// publish parses JSON response into native JavaScript objects
}
Obviously there are a few components in between.
When I make any future requests to other APIs, I'll include that jwttoken in the header. (I'm not sure why I repeat the word token here.)
AND add a conditional for a 401 response to change the jwtholder state.

Why is Axios not using the Content-Type header and converting the request method to GET when PATCHing to a specific URL?

I have inherited a codebase using Axios, and I am otherwise unfamiliar with the library. This is a Node application, and I'm attempting to send a PATCH request to a third party API. Axios is configured using the following:
const axios = require('axios').create({
baseURL: process.env.API_URL,
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
auth: {
username: process.env.API_USER,
password: process.env.API_PW,
},
});
I then try to make the following PATCH request:
const data = {
fields: {
field_a: 'yes',
field_b: 'no',
},
};
try {
const res = await axios.patch(`/user/${user.id}`, data, {
headers: {
'Content-Type': 'application/json'
}
});
return res;
} catch (err){
console.error(err);
}
From what I can see I'm just redefining the Content-Type header when making the patch call, but that was just an attempt to figure this out. It doesn't work either way. What I see in the response object's config property is the following (most of it is excluded):
{
headers: {
Accept: "application/json"
User-Agent: "axios/0.19.0"
},
method: 'patch',
}
Looking at the request property of the same response object I see that the method there is listed as "GET" with the Content-Type header also not listed there. It appears as though the Content-Type header is being stripped and the method is being changed to GET.
If I change nothing but the URL destination to /userWRONGPATH/${user.id} I receive, as expected, a 404 response, but the response object's config data includes this:
{
headers: {
Accept: "application/json"
Content-Length: 105
Content-Type: "application/json"
User-Agent: "axios/0.19.0"
}
}
The response object's request method is now the expected 'PATCH'. I am unsure why the patch method would work for other paths if that is in fact what is happening here.
Hello I think that the problem could be related of send the header again in Axios you define a config and that is added to all the requests.
This is an example that I use to order the project with axios.
// Axios custom config
const axiosInstance = axios.create({
baseURL: urlBase,
// timeout: 1000,
headers: { 'Content-type': 'application/json' },
});
export const apiPatchRequest = (url, id, obj) => (
axiosInstance.patch(`${url}/${id}`, obj)
);

React - GET and POST requests with axios

In my application I need to GET some data (for which I provide the native authtoken).
In the same event, however, I also need to POST a second token to be consumed by a few endpoints, for external backend api calls.
How do I POST this second token using my working code below using axios?
Should I extend Authorization bearer or simply POST Spotify Token as string data?
How so?
My code:
getData(event) {
const {token} = this.props.spotifyToken
const options = {
url: `${process.env.REACT_APP_WEB_SERVICE_URL}/endpoint`,
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.authToken}`
}
};
return axios(options)
.then((res) => {
console.log(res.data.data)
})
.catch((error) => { console.log(error); });
};
For an async await applied to your code would look something like this.
async getData(event) {
const {token} = this.props.spotifyToken
let getRes = await axios.get(`${process.env.URL}/endpoint` {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${window.localStorage.authToken}`
}
}
let postRes = await axios.post(`${process.env.URL}/endpoint` {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${window.localStorage.authToken}`
}
}
console.log(getRes.data.data);
console.log(postRes.data.data);
};
In this specific case, where a token is needed to fetch data at backend, I found that passing token at url is more suitable, like so:
#endpoint.route('/endpoint/<select>/<user_id>/<token>', methods=['GET'])
def endpoint(name, user_id, token):
# business logic
and:
const options = {
url: `${process.env.REACT_APP_WEB_SERVICE_URL}/endpoint/${select}/${userId}/${this.props.spotifyToken}`,
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.authToken}`
}
};
otherwise, backend code would run twice, for POST and GET, which is not desired in my case.

When using mode: no-cors for a request, browser isn’t adding request header I’ve set in my frontend code

in my React app, I have the following API POST to allow the user to edit their profile (name and image).
static updateProfile(formData, user_id) {
const request = new Request(`http://localhost:4300/api/v1/profiles/${user_id}`, {
headers: new Headers({
'Authorization': getBearerToken()
}),
mode: 'no-cors',
method: "POST",
body: formData
});
return fetch(request).then(response => {
return response.json();
}).catch(error => {
return error;
});
}
The problem with the above is the header with the Authorization token is not being sent in the POST...
How can I get the Authorization header to be send in the fetch request above?
FYI, for non-multipart forms, the authorization token is sent successfully like so:
static loadProfile(user_id) {
const request = new Request(`http://localhost:4300/api/v1/profiles/${user_id}`, {
headers: new Headers({
'Authorization': getBearerToken(),
'Accept' : 'application/json',
'Content-Type' : 'application/json',
})
});
return fetch(request).then(response => {
return response.json();
}).catch(error => {
return error;
});
}
You can’t use no-cors mode if you set any special request headers, because one of effect of using it for a request is that it tells browsers to not allow your frontend JavaScript code to set any request headers other than CORS-safelisted request-headers. See the spec requirements:
To append a name/value pair to a Headers object (headers), run these steps:
Otherwise, if guard is "request-no-cors" and name/value is not a CORS-safelisted request-header, return.
In that algorithm, return equates to “return without adding that header to the Headers object”.
Authorization isn’t a CORS-safelisted request-header, so your browser won’t allow you to set if you use no-cors mode for a request. Same for Content-Type: application/json.
If the reason you’re trying to use no-cors mode is to avoid some other problem that occurs if you don’t use, the solution is to fix the underlying cause of that other problem. Because no matter what problem you might be trying to solve, no-cors mode isn’t going to turn out to be a solution in the end. It’s just going to create different problems like what you’re hitting now.
By using below code you can make a fetch request with Authorization or bearer
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
}));

Categories