Force fetched image data to https - javascript

I am looking for a solution to force images from a fetch API to be in https rather than http
The API returns image results as http from the fetched JSON file but this is giving warning in the console to Mixed Content
I am fetching in componentDidMount as
componentDidMount() {
var self = this;
const proxyurl = 'https://cors-anywhere.herokuapp.com/';
const url = `//api.tripadvisor.com/api/partner/2.0/location/${this.props
.tripAdvisorId}?key=${AuthKey}`;
fetch(proxyurl + url)
.then(data => data.json())
.then(data => {
self.setState({
reviewData: data,
isLoading: false
});
});
}
and then mapping the data by way
{this.state.reviewData.reviews.map(i => {
return (
<div key={i.id}>
<img src={i.rating_image_url} alt={i.title} />
</div>
);
})}
How can I force the url from {i.rating_image_url} to use https when this is not returned from the fetch?

By using a regular expression, something like:
{this.state.reviewData.reviews.map(i => {
return (
<div key={i.id}>
<img src={i.rating_image_url.replace(/^http:\/\//i, 'https://')} alt={i.title} />
</div>
);
})}

const url = new URL(originalUrl);
url.protocol = url.protocol.replace('http', 'https');
console.log(url.href);
This method uses the built-in URL class to fully parse, and then uses a string replacement on the protocol.

Just change this code to check if you are receiving the image or not
<img src={i.rating_image_url ? i.rating_image_url : i.rating_image_url.replace(/^http:\/\//i, 'https://')} alt={i.title} />
This way we are checking if we are getting its value or not.
For more better understanding you can also do this
{this.state.reviewData.reviews.map(i => {
console.log(i.rating_image_url);
return (
<div key={i.id}>
<img src={i.rating_image_url} alt={i.title} />
</div>
);
})}
This will show whatever data you are receiving in rating_image_url on your browser console.
Hope it helps you.

Related

CORS No 'Access-Control-Allow-Origin' error in React app w/ Facebook

I'm a junior developer that's fairly new to using Facebook for Developers. I'm hitting a wall with the ReactJs application I'm building and could use your help!
My boss has requested a Grid representation of the Page Plugin, not the actual Plugin itself. For this project, he's requested I make and use a test 'Page' I've found that DevExtreme's Data Grid seems to be the best option in terms of the desired visual, and I'm trying to call my Facebook Page using the Graph API documentation. I know it's hitting at least the area I want it to with my console.log because it's returning the error message.
Here are the errors my browser is returning:
Access to fetch at 'https://www.facebook.com/Feeds-Tester-170107151801959/' from origin 'https://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
GET https://www.facebook.com/Feeds-Tester-170107151801959/ net::ERR_FAILED
The link you'll see referenced in my URL variable has been triple checked to be the correct link. Since I'm using NodeJS, I tried installing the CORS npm package but I'm not 100% sure where to put it to use it, I'm wondering if that's the cause of the issue?
Here's my full code snippet (I'm using VS Code, if that helps):
/*global FB*/
import React from 'react';
import { DataGrid, Editing, Scrolling, Lookup, Summary, TotalItem } from 'devextreme-react/data-grid';
import { Button } from 'devextreme-react/button';
import { SelectBox } from 'devextreme-react/select-box';
import CustomStore from 'devextreme/data/custom_store';
import { formatDate } from 'devextreme/localization';
import 'whatwg-fetch';
const URL = 'https://www.facebook.com/Feeds-Tester-170107151801959/';
const REFRESH_MODES = ['full', 'reshape', 'repaint'];
class Grid extends React.Component {
constructor(props) {
super(props);
this.state = {
fbData: null,
ordersData: new CustomStore({
key: 'OrderID',
load: () => this.sendRequest(`${URL}`, 'GET'),
}),
requests: [],
refreshMode: 'reshape'
};
this.clearRequests = this.clearRequests.bind(this);
this.handleRefreshModeChange = this.handleRefreshModeChange.bind(this);
var body = 'Reading JS SDK documentation';
FB.api('/me/feed', 'post', { message: body }, function(response) {
if (!response || response.error) {
console.log('Error occured');
} else {
console.log('Post ID: ' + response.id);
}
})
}
sendRequest(url, method, data) {
method = method || 'GET';
data = data || {};
this.logRequest(method, url, data);
if(method === 'GET') {
return fetch(url, {
method: method,
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
'Access-Control-Allow-Origin': '*'
}
}).then(result => result.json().then(json => {
if(result.ok) return json.data;
throw json.Message;
}));
}
const params = Object.keys(data).map((key) => {
return `${encodeURIComponent(key) }=${ encodeURIComponent(data[key])}`;
}).join('&');
return fetch(url, {
method: method,
body: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
credentials: 'include'
}).then(result => {
if(result.ok) {
return result.text().then(text => text && JSON.parse(text));
} else {
return result.json().then(json => {
throw json.Message;
});
}
});
}
logRequest(method, url, data) {
const args = Object.keys(data || {}).map(function(key) {
return `${key }=${ data[key]}`;
}).join(' ');
const time = formatDate(new Date(), 'HH:mm:ss');
const request = [time, method, url.slice(URL.length), args].join(' ');
this.setState((state) => {
return { requests: [request].concat(state.requests) };
});
}
clearRequests() {
this.setState({ requests: [] });
}
handleRefreshModeChange(e) {
this.setState({ refreshMode: e.value });
}
render() {
const { refreshMode, ordersData } = this.state;
return (
<React.Fragment>
<DataGrid
id="grid"
showBorders={true}
dataSource={ordersData}
repaintChangesOnly={true}
>
<Editing
refreshMode={refreshMode}
mode="cell"
allowAdding={true}
allowDeleting={true}
allowUpdating={true}
/>
<Scrolling
mode="virtual"
/>
<Lookup dataSource={ordersData} valueExpr="Value" displayExpr="Text" />
<Summary>
{/* <TotalItem column="CustomerID" summaryType="count" />
<TotalItem column="Freight" summaryType="sum" valueFormat="#0.00" /> */}
</Summary>
</DataGrid>
<div className="options">
<div className="caption">Options</div>
<div className="option">
<span>Refresh Mode: </span>
<SelectBox
value={refreshMode}
items={REFRESH_MODES}
onValueChanged={this.handleRefreshModeChange}
/>
</div>
<div id="requests">
<div>
<div className="caption">Network Requests</div>
<Button id="clear" text="Clear" onClick={this.clearRequests} />
</div>
<ul>
{this.state.requests.map((request, index) => <li key={index}>{request}</li>)}
</ul>
</div>
</div>
</React.Fragment>
);
}
}
export default Grid;
This is the link to the docs for the module I'm trying to reference
I'm trying to not bite off more than I can chew and just start with retrieving the data before I even think about manipulating it or sending any in return. Any insight or guidance you can provide would be greatly appreciated. Thank you!! :)
Do not use fetch with the Facebook URL, it won't let it happen on the browser, instead, use the Facebook API for everything you need to do with it
For example, instead of fetching the page, use the api with the page
FB.api('/Feeds-Tester-170107151801959', function(response) {
// ...
});
If you need to fetch the page, then you have to do it outside the browser environment or use a proxy like cors anywhere, but you can avoid that by using the Facebook API
I was also getting these error. I found that the pageId, I was using was wrong🤦‍♀️. These errors come only when your pageId is wrong or the domain is not whitelisted properly(I even tried with a ngrok url and it worked😵).
So the steps which I followed were:
In buisness.facebook.com go to inbox from sidebar and select chat plugin. [https://i.stack.imgur.com/rDk5d.png]
Click on setup to add your domain. [https://i.stack.imgur.com/exOi2.png]
Pick a setup method(standard for react/nextjs) and setup chat plugin(add language, domain, copy code and paste it). [https://i.stack.imgur.com/hDArZ.png]
You can add multiple domains. [https://i.stack.imgur.com/zGdgx.png]
You will get pageId already embedded. [https://i.stack.imgur.com/iRT13.png]
Use this code and paste it in _document.js file in nextjs. and after deploying it will work perfectly. For any confusion please let me know. Thanks, Happy Coding ☺

react-pdf from ByteArray response?

I am trying to request a PDF file from my java server through a react typescript app. Then trying to display this byte[] through react-pdf.
The request to the server looks like this:
const [invoice, setInvoice] = React.useState<any>()
const downloadPdf = (theInvoice: Invoice) => {
store.app.cubaRest?.invokeService<any>('billing_InvoiceService', 'generateInvoiceDocument', { invoice: theInvoice })
.then((response: any) => {
console.log(response)
let array= JSON.parse(response).content
setInvoice(array)
}).finally(()=>{
})
}
if (invoice) {
console.log("there is invoice")
return (
<div>
<Document
file={{ data: invoice }}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={console.error}
>
<Page pageNumber={pageNumber} />
</Document>
</div>
The console log from the raw "response" above looks like this:
{"report":{"_entityName":"report$Report","id":"1dd6746f-3580-6e3c-3aa6-e3f5db0a290b","code":"default-invoice","roles":[],"defaultTemplate":{"id":"0de287de-1931-a375-d10f-70ae431a3ca7","content":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGggSmFzcGVyc29mdCBTdHVkaW8gdmVyc2lvbiA2LjE2LjAuZmluYWwgdXNpbmcgSmFzcGVyUmVwb3J0cyBMaWJyYXJ5IHZlcnNpb24gNi4xNi4wLTQ4NTc5ZDkwOWI3OTQzYjY0NjkwYzY1YzcxZTA3ZTBiODA5ODE5MjggIC0tPgo8amFzcGVyUmVwb3J0IHhtbG5zPSJodHRwOi8vamFzcGVycmVwb3J0cy5zb3VyY2Vmb3JnZS5uZXQvamFzcGVycmVwb3J0cyIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnNjaGVtYUxvY2F0aW9uPSJodHRwOi8vamFzcGVycmVwb3J0cy5z .......
When I set the state from the response the page just keeps rerendering and the pdf does not show. Presumably it is doing a re-render for every byte in the byte array.
Not sure how to resolve this. Also not sure if I am sending the byte[] correctly to setInvoice either. Or if the byteArray is in the correct format for that matter.
Was quite a simple solution.
instead of:
let array= JSON.parse(response).content
setInvoice(array)
do:
setInvoice({data: JSON.parse(response).content});
if (invoice) {
return (
<div>
<Document
file={invoice}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={console.error}
>
<Page pageNumber={pageNumber} />
</Document>
</div>
Heres the base64 approach
1. Given base64 string of the pdf file
const fileAsBase64 = || YOUR PDF FILE IN BASE64 AS STRING ||
2. Convert base64 string to bytearray
export const base64ToArrayBuffer = (base64) => {
const binaryString = window.atob(base64); // Comment this if not using base64
const bytes = new Uint8Array(binaryString.length);
return bytes.map((byte, i) => binaryString.charCodeAt(i));
}
3. Add the byearray to component by calling above function
<Document file={{ data :base64ToArrayBuffer(base64)}}/>

React component renders before I can set src of image

I have this application that flashes a series of cards. Some have questions with text. No problem there obviously. But the image source is being retrieved from firebase. On each render I check if it has a question with text, or with an image and if it has an image I query the database for the downloadURL and insert that as the source. If I insert it hard coded it works fine, if I console log the response it's accurate. My problem is I believe that the component renders before I can insert the source dynamically. Code is below. And yes, I know with that many conditionals it looks like a christmas tree and is probably really bad practice.
To save some reading I'll splice it where I make the request here...
useEffect(() => {
if ("imageHolder" in active) {
const asyncFunc = async () => {
setLoading(true);
setImage(true);
await storageRef
.child(active.imageHolder)
.getDownloadURL()
.then(function (url) {
imageSrc = url;
console.log("url returns ", url);
})
.catch(function (error) {
console.log(error);
});
};
asyncFunc();
setLoading(false);
}
}, [active, getQuestions, correctAnswer]);
And where I insert it here
) : image ? (
loading ? (
<h1>Loading</h1>
) : (
<img alt="" src={imageSrc} className="d-inline-block align-top" />
)
) : (
<h3>{active.question}</h3>
)}
</div>
<div className="answerGrid">
{loading ? (
Thanks for any advice at all. And stay healthy!
It might be helpful to see the rest of the code, but given the provided snippets, I'm assuming the problem is with how the imageSrc variable is getting set.
Have you tried managing the imageSrc as state? E.g.
const [imageSrc, setImageSrc] = useState('')
// then use setImageSrc after getting the url
await storageRef
.child(active.imageHolder)
.getDownloadURL()
.then(function (url) {
setImageSrc(url)
console.log("url returns ", url);
})
I think simple decision to this will be adding a logical "or" operator in src
like this
<img alt="" src={imageSrc || ''} className="d-inline-block align-top" />

Fetch request renders undefined in html

I have this Vanilla JS code inside my html block
<label for="weather"></label><input value="copenhagen" type="text" id="weather" placeholder="Enter your name to get weather">
<button onClick="getValue()">Submit</button>
<div id="weather-box"></div>
<script>
function getValue() {
const form = document.getElementById('weather').value;
const weatherBox = document.getElementById('weather-box')
console.log(form);
fetch(`http://localhost:3000/weather?city=${form}`)
.then(res => res.json())
.then(data => {
console.log(data)
weatherBox.innerHTML = `
weather is ${data.summary}
temperature is ${data.temperature}
`
})
}
</script>
the problem is that, even though the data is logged out correctly, it gives undefined inside the rendered html code.
Why is this happening, and how cani fix it?
EDIT:
I have added the output from the console.log(data)
Your console.log(data) indicates that your response (data) has a property also called data, which holds the information you want.
You could access it via data.data.summary (or better yet, rename your response to something like response).
An alternative would be to destructure it:
.then(({data}) => {
weatherBox.innerHTML = `
weather is ${data.summary}
temperature is ${data.temperature}
`
})

How do I get my api call to call a different file?

I am using the api http://aws.random.cat/meow and it gives me a result of
{"file": "https://purr.objects-us-east-1.dream.io/i/rEJ7q.jpg"}
The file changes every time I refresh the api call on the browser which gives me a different cat pic. For example, if I refresh it would give me a different .jpg like
{"file": "https://purr.objects-us-east-1.dream.io/i/ferbus.jpg"}
I call the api in my React app, and I want to randomize the cat pic after an onClick of a button. Unfortunately, I get the same picture back when I do my api call. I put the file in an img src, but it doesn't change when I do another api call.
componentDidMount() {
this.getCats();
}
getCats = () => {
axios.get(`http://aws.random.cat/meow`)
.then(res => {
let cats = res.data.file;
console.log(cats)
this.setState({
cats
})
})
.catch(err => console.log(err))
}
render() {
return (
<div>
<img
src={this.state.cats}
alt='cat'
/>
<button onClick={this.getCats}>
Click me
</button>
</div>
);
}
I expect to get a different file every time, but instead I get the same .jpg when I do an onClick.

Categories

Resources