I have one React Amplify app running with two environments. One environment is for my wife's blog (www.riahraineart.com) and one for my blog (www.joshmk.com). Both sites are running off the same repo, I'm just configuring the site's differently based on an environment variable I use to retrieve their configurations from a table.
useEffect(() => {
async function fetchData() {
const configData = await API.graphql({
query: queries.getConfiguration,
variables: { id: process.env[configIdName] },
});
if (configData && isMounted.current)
setConfig(configData.data.getConfiguration || {});
}
if (process.env[configIdName]) {
fetchData();
}
}, [isMounted, configIdName]);
For my site, when I make the GraphQL request for this configuration, it's successful and the site spins up. For my wife's site, this call to the configurations table silently fails. By silent, I mean there's no helpful response being returned from the API even though it's a successful 200 response.
When I open AppSync, go to the two environments and run the queries, I receive the configuration items. I also see them when I open dynamodb.
I'm thinking there could be some expired token for something somewhere but if that was the case, I would think I'd receive a failed response that would state that.
Another possibility could be that my wife had modified the configuration of her site or created a post with some content that the frontend doesn't expect. But in that case, I would atleast expect to see a response from the call to receive her sites configuration.
Thank you beforehand for any insights here!
I fixed it! Unfortunately, the solution was pretty specific to my situation so it may not provide too much value for others. Although, I hope it helps with troubleshooting.
After locally switching my backend configuration over to her site using amplify pull --appId <appId> --envName <envName> I noticed that the configuration call was now successful. I had forgotten that I had never actually run her site locally, I only hopped to her branch to merge and push.
The site was still not rendering though, which perked my ears for a race condition. I discovered that I had left a checker for some images that was gating render of my topmost component. My wife has a ton of images, so I think this call was taking too long to make the chain of events load items in the correct order, and the page showed blank. Simply removing that check for those images at that point, showed the UI.
Related
Firstly, I am fairly new to both React and Shopify, so please bear that in mind with your answers.
I have created a basic Shopify app using their CLI tools which provide a React app. I now need to connect this app to a third party that manages custom shipping options. I therefore need to authenticate with this third party which then returns a token which I can use in my API calls. I've read many answers here about storing such tokens, some recommend localstorage/cookies, others state never do that but don't provide a clear answer to what one SHOULD do instead.
Currently I have something like the following:
let data = {
grant_type: 'client_credentials',
client_id: process.env.REACT_APP_THIRDPARTY_API_KEY,
client_secret: process.env.REACT_APP_THIRDPARTY_API_SECRET
}
axios.post('https://oauth.somethirdparty.se/v1/token', data).then(res => {
if (typeof window !== 'undefined') { // Check for browser
localStorage.setItem('t', res.data.token);
}
});
However I receive "undefined" errors for those env vars, and therefore the axios.post fails (works fine if I put in the key/secret directly here instead of the .env). Aside from this being unsecure according to the many posts here, I'm wondering if I can perhaps do something similar to what Shopify is doing, only my lack of knowledge prevents me from understanding exactly it is that they are doing!
The generated Shopify app uses the .env file in it's server.js file, like so:
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
API_VERSION: ApiVersion.October20,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
How can one safely store API credentials in my case? And please provide an actual example.
EDIT
I've found that if I modify the Shopify server.js file to console.log(process.env), I see all of the used env vars in the Terminal, and I guess the reason these are "undefined" when I try to log them in my app component is intentional so they are not exposed, which is great. Unfortunately it still doesn't help me when I need to connect to a third party service and get a token etc - how do I do that in this case?
This is a very easy question to answer. It is true, you always want to store your secrets in something like a dotenv file. Modern advanced frameworks like Rails even let you encrypt those, although eventually, you do need to ensure a secret key is present on your server for that.
So your public hosting service allows you to set environment variables. That is where you ensure they exist. You do not check those values into your public/private GitHub copy of your code.
So now, when your code executes, it has access to your secrets. It seems when you run your code, and you get undefined values, it is due to this, you have failed to set your environment properly. Read the documentation at your hosting service to figure that out.
Note that Shopify is not unique, 99% of all services operate this way. So you should have no trouble finding an answer to your problem.
I'm running PageSpeed Insights on my website and one big error that I get sometimes is
Reduce initial server response time
Keep the server response time for the main document short because all
other requests depend on it. Learn more.
React If you are server-side rendering any React components, consider
using renderToNodeStream() or renderToStaticNodeStream() to allow
the client to receive and hydrate different parts of the markup
instead of all at once. Learn more.
I looked up renderToNodeStream() and renderToStaticNodeStream() but I didn't really understand how they could be used with Gatsby.
It looks like a problem others are having also
The domain is https://suddenlysask.com if you want to look at it
My DNS records
Use a CNAME record on a non-apex domain. By using the bare/apex domain you bypass the CDN and force all requests through the load balancer. This means you end up with a single IP address serving all requests (fewer simultaneous connections), the server is proxying to the content without caching, and the distance to the user is likely to be further.
EDIT: Also, your HTML file is over 300KB. That's obscene. It looks like you're including Bootstrap in it twice, you're repeating the same inline <style> tags over and over with slightly different selector hashes, and you have a ton of (unused) utility classes. You only want to inline critical CSS if possible; serve the rest from an external file if you can't treeshake it.
Well the behavior is unexpected, I ran the pagespeed insights of your site and it gave me a warning on first test with initial response time of 0.74 seconds. Then i used my developer tools to look at the initial response time on the document root, which was fairly between 300 to 400ms. So I did the pagespeed test again and the response was 140ms. The test was passed. After that it was 120ms.
See the attached image.
I totally think there is no problem with the site. Still if you wanna try i would recommend you to change the server or your hosting for once, try and go for something different. I don't know what kind of server you have right now where the site is deployed. You can try AWS S3 and CloudFront, works well for me.
I am new in front-end/client-side app development for website. I am setting up a new react project. I used create-react-app.
How should I handle the console errors(other than network call errors)? Is there a way to log them in any file?
What are the best logging practices?
Even though there are means and ways to store data on the browser (not to actual client files) that's not really the general strategy for logging browser errors (which I believe is what you're referring to).
In my experience we'd have a dedicated logging server with a simple API with adequate security that filters traffic and applies rate limiting. That would finally enhance and write logs into a document database that can later be analysed.
A naive JavaScript solution would be using the following to capture errors and send them out to a logging server.
window.onerror = function(message, url, lineNumber) {
// make ajax call to api to save error on server
return true;
};
I should also mention Sentry.io - they provide a service that does this and even though there are some limitations they're usually enough for a small to mid app.
https://github.com/getsentry
UPDATE: Please, if anyone can help: Google is waiting for inputs and examples of this problem on their bug tracking tool. If you have reproducible steps for this issue, please share them on: https://code.google.com/p/googleappengine/issues/detail?id=10937
I'm trying to fetch data from the StackExchange API using a Google App Engine backend. As you may know, some of StackExchange's APIs are site-specific, requiring developers to run queries against every site the user is registered in.
So, here's my backend code for fetching timeline data from these sites. The feed_info_site variable holds the StackExchange site name (such as 'security', 'serverfault', etc.).
data = json.loads(urllib.urlopen("%sme/timeline?%s" %
(self.API_BASE_URL, urllib.urlencode({"pagesize": 100,
"fromdate": se_since_timestamp, "filter": "!9WWBR
(nmw", "site": feed_info_site, "access_token":
decrypt(self.API_ACCESS_TOKEN_SECRET, self.access_token), "key":
self.API_APP_KEY}))).read())
for item in data['items']:
... # code for parsing timeline items
When running this query on all sites except Stack Overflow, everything works OK. What's weird is, when the feed_info_site variable is set to 'stackoverflow', I get the following error from Google App Engine:
HTTPException: Invalid and/or missing SSL certificate for URL:
https://api.stackexchange.com/2.2/me/timeline?
filter=%219WWBR%28nmw&access_token=
<ACCESS_TOKEN_REMOVED>&fromdate=1&pagesize=100&key=
<API_KEY_REMOVED>&site=stackoverflow
Of course, if I run the same query in Safari, I get the JSON results I'm expecting from the API. So the problem really lies in Google's URLfetch service. I found several topics here on Stack Overflow related to similar HTTPS/SSL exceptions, but no accepted answer solved my problems. I tried removing cacerts.txt files. I also tried making the call with validate_certificate=False, with no success.
I think the problem is not strictly related to HTTPS/SSL. If so, how would you explain that changing a single API parameter would make the request to fail?
Wait for the next update to the app engine (scheduled one soon) then update.
Replace browserid.org/verify with another service (verifier.loogin.persona.org/verify is a good service hosted by Mozilla what could be used)
Make sure cacerts.txt doesnt exist (looks like you have sorted but just in-case :-) )
Attempt again
Good luck!
-Brendan
I was facing the same error, google has updated the app engine now, error resolved, please check the updated docs.
I have implemented Google App Engine's Channel API feature in my application. Everything runs smoothly. I create new channels every one hour for every user. I have managed to maintain one channel per session (same channel for different tabs in a browser). I have implemented the onerror and onclose methods in such a way that every time they are invoked, a call is made to the server requesting for a valid token.
Sometimes, after the channel's been alive for a while, it gets disconnected. I can see failed HTTP calls to talkgadget.google.com on the JavaScript console. The URLs are something like this:
https://129.talkgadget.google.com/talkgadget/dch/bind?VER=8&clid=.....
These calls have responses like "401 (Token timed out)" or "401 (Token invalid)".
Which is indeed true, the token used by the client is invalid. It should get updated with the new token but the onerror or onclose methods aren't invoked. How am I supposed to figure out when this would happen or how to handle it? There is no real way to say if a client is disconnected or not except for the onerror or onclose methods. This issue is resolved if I refresh the page (I get the valid token from database every time the user refreshes).
I checked the socket objects's "readyState" property and it had the value 1. There are many who face this issue and as of date, there seems to be no valid solution offered by the folks at GAE.
Edit: I'm a premium account holder and this issue is holding back our deployments.
Edit 2: Having one channel per tab reduces the frequency of this happening. But it doesn't solve the problem completely.
It has been six days since I posted the question and there has been no response from the AppEngine team or any other users.
The workaround I applied was to have a button on the site that would fetch the (valid) token from the database, close the channel and then open it again with the token received.
Sometimes its a new token which should've been received before, sometimes its the same token that had been valid all along.
This issue cannot be replicated often I agree, but when it happens, it causes a lot of damage. I hope I find a solution soon.
Edit: Having one channel per tab reduces the frequency of this happening. But it doesn't solve the problem completely.