How to expose lamba endpoint in serverless.yml only for dev stage? - serverless

I'd like to have a debug endpoint available only for stage. One way to do it is to the authorization in server code, but it would be even better not to create the API Gateway endpoint all together. Is it possible to achieve using Serverless framework?

In Serverless Framework, you can use a switch based on your environment to toggle configuration options, within the context of your YAML file.
For example, if you wanted to setup a normal HTTP endpoint via API Gateway you'd add something like the following to your functions section:
functions:
ping:
handler: "src/functions/ping/handler.main"
events:
http:
method: "any"
path: "/ping"
If you want this http event to be available for only a certain stage, you can define a block elsewhere and reference it based on the current stage name. It's commonplace to use the custom block in your serverless.yml file for this. To isolate between the stages prod and dev, with dev being your staging area you'd do this:
custom:
pingEvents: "${opt:stage, self:provider.stage}"
prod:
http:
method: "any"
path: "/ping"
dev:
http:
functions:
ping:
handler: "src/functions/ping/handler.main"
events: "${self:custom.pingEvents.${opt:stage, self:provider.stage}}"
The above would only expose the endpoint via HTTP when you run sls deploy --stage dev to release your application; any other stage (e.g. – prod) will have it disabled. Do note, that in this example, if you want to support stages outside of dev and prod you'll need to add a new block under custom.pingEvents.

Related

How to declare conditional resource in serverless framework

I use typescript definition of serverless configuration (serverless.ts). How do I conditionally add resources using cloud formation templates ?
For example AWS cognito userpools, if I want to exclude these for offline mode, how can I specify it in serverless config file to not include them?
I solved it 2 ways. serverless-plugin-ifelse allowed me to exclude resources based on certain parameters.
Later I realized this may be problematic in the long run. So I created separate serverless config file for my offline use case to include all necessary resources. Prod/Staging environments used default serverless.ts file. Offline uses offline-serverless.ts file. Though there is some repetition of the resources config, this option ensures prod/staging config is not polluted with offline content. I could start offline using sls offline start --stage local --reloadHandler --config offline-serverless.ts
And the offline config reuses some code from main config. Sample offline-serverless.ts content is below:
import offlineplugins from "offlineplugins";
import pluginsconfig from "offlinepluginsconfig";
import plugins from "plugins";
const serverlessConfiguration: AWS = {
service: "my-offline-apis",
frameworkVersion: "3",
...pluginsconfig,
plugins: [...plugins, ...offlineplugins],
provider: {
name: "aws",
....
....

read environment variable in vuejs application after creating build or docker image

I am building a docker image for my vuejs app. And I want some environment variable to read by my vuejs application.
For example:
I want to change my 'baseUrl' after creating and building the image, in runtime environment.
What I've tried & Search is:
It says you can not read outside an application after creating vuejs application build.
Check the docs of React example. You can inject to the html any variable at runtime (from backend, server side). Here the simple schema used in React.
html:
<script>
window.SERVER_DATA = __SERVER_DATA__;
</script>
client:
const constants = {
debug: false,
port: 8443,
host: window.SERVER_DATA,
graphql: {
path: '/graphql'
},
}
On the server side use the functions to pipe (and change your variable) the html output to client.

How to service a Gatsby website with multiple domains and its contents?

I built a website using Gatsby, Contentful, and deployed on Netlify.
I am going to run this website with multiple domain aliases.
ex:
alias1.example.com
alias2.example.com
In that case, the aliases work well and the website have to show contents that belong to the own alias in Contentful.
For example, let's say the current alias is alias1, then the website have to fetch data only have alias1 entry from Contentful.
What I was trying is to add the codes to identify alias in gatsby-config.js using windows.location.href, and set siteUrl as dynamic, but it didn't work.
I am not sure it could be possible and how to implement it.
Thank you.
The best (and almost the only) approach to achieving this is to use an environment variables for each site/alias and configure the deploy command to trigger and use the variables for each site. In that way, each deploy will fetch the data from each Contentful environment.
In your gatsby-config.js (above the module exportation) add:
require("dotenv").config({
path: `.env.${process.env.NODE_ENV}`,
})
The next step is to create one environment file for each alias. In your project root:
.env.alias1
.env.alias2
Each file should contain your environment variables from Contentful:
CONTENTFUL_ACCESS_TOKEN:12345
CONTENTFUL_SPACE_ID:12345
Then, in your gatsby-config.js just replace your hardcoded variables for the ones in your environment files:
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: process.env.CONTENTFUL_SPACE_ID,
accessToken: process.env.CONTENTFUL_ACCESS_TOKEN,
},
},
The last step is to configure the deploy scripts to trigger each desired alias. In your package.json:
"scripts": {
"clean": "gatsby clean",
"test": "jest",
"format": "prettier --write \"**/*.{js,jsx,json,md}\""
"develop-alias1": "gatsby develop GATSBY_ACTIVE_ENV=alias1"
"build-alias1": "gatsby build GATSBY_ACTIVE_ENV=alias1"
"develop-alias2": "gatsby develop GATSBY_ACTIVE_ENV=alias2"
"build-alias2": "gatsby build GATSBY_ACTIVE_ENV=alias2"
},
Note that you will replace the default gatsby develop and gatsby build for your aliased commands.
By adding this bunch of configuration, for each develop or build/deploy you are telling your Gatsby project to which environment file should look at (it will take your .env.alias* instead). Each file will contain the keys for each environment in Contentful with different content in it, allowing you to deploy aliased sites with different content using a unique CMS.
This might be the most critical problem of Gatsby, and almost people has hard time with it.
The core problem is the "browser environment" is not available when you "build" Gatsby project. And gatsby-config.js is used for NodeJS environment. In other words, everything sticked with window variable is not accessible.
You should read the offical docs about gatsby build process here:
https://www.gatsbyjs.com/docs/overview-of-the-gatsby-build-process/#build-time-vs-runtime.
Solution: you can define different "scripts" in package.json for each alias which you can provide environment variables for NodeJS environment. Then in gatsby-config.js, use dotenv package to read passed variables.
You can read more here about using environment variables: https://www.gatsbyjs.com/docs/environment-variables/#reach-skip-nav

Nuxt environment variables exposed in client when uploaded to Zeit/Now

I am deploying a Nuxt App with Zeit/Now. In the development phase I was using a .env file to store the secrets to my Contentful CMS, exposing the secrets to process.env with the nuxt-dotenv package. To do that, at the top of the nuxt.config I was calling require('dotenv').config().
I then stored the secrets with Zeit/Now and created a now.json to set them up for build and runtime like so:
{
"env": {
"DEMO_ID": "#demo_id"
},
"build": {
"env": {
"DEMO_ID": "#demo_id"
}
}
}
With that setup, the build was only working for the index page and all of the Javascript did not function. Only when I added the env-property to the nuxt.config.jsfile, the app started working properly on the Zeit-server.
require('dotenv').config()
export default {
...
env: {
DEMO_ID: process.env.DEMO_ID
},
...
modules: [
'#nuxtjs/dotenv'
],
...
}
BUT: When I then checked the uploaded Javascript files, my secrets were exposed, which I obviously don't want.
What am I doing wrong here? Thanks for your help.
You aren't necessarily doing anything wrong here, this is just how Nuxtjs works.
Variables declared in the env property are used to replace instances of process.env.MY_ENV, but because Nuxt is isomoorphic, this can be both on the server and client.
If you want these secrets accessible only on the server, then the easiest way to solve this is to use a serverMiddleware.
As serverMiddleware is decoupled from the main Nuxt build, env variables defined in nuxt.config.js are not available there.
This means your normal ENV variables should be accessible, since the server middleware are run on Node.
Obviously, this means these secrets won't be available client side, but this works if you have something like a Stripe secret key that you need to make backend requests with.
We had a similar problem in our project. Even, We created a nuxt project from scratch and checked to see if there was a situation we skipped. We noticed that, while nuxt building, it copies the .env variables into the utils.js in the nuxt folder. Through the document here, we changed the modules section in nuxt.config.js as follows,
modules: ['# nuxtjs / apollo', '# nuxtjs / axios', ['# nuxtjs / dotenv', { only: ['']}]],
Then we noticed that .env variables are not exposed.
I hope it helped.
Our nuxt version is "nuxt": "^ 2.13.0".
Also, some discussion over here.

VueJS & Webpack: ENV var unaccessible from built project

I'm working on an app with vuejs frontend and nodejs backend. My frontend makes API https requests to the backend. I've started my projet with vue-cli and webpack.
I need to get the backend API url from env variable (BACKEND_URL).
Since i'm using webpack, I added this line to config/prod.env.js :
module.exports = {
NODE_ENV: '"production"',
-> BACKEND_URL: JSON.stringify(process.env.BACKEND_URL)
}
It works flawlessly in dev mode using webpack-dev-server. I pass the env var throught docker-compose file:
environment:
- BACKEND_URL=https://whatever:3000
But when I run build, I use nginx to serve the static files (but the problem is the same using visual studio code live server extension). I send BACKEND_URL env var the same way as before. The thing is now the process.env.BACKEND_URL is undefined in the app (but defined in the container)!! So I cant make backend http calls :(
I'm struggling finding the problem, please don't be rude with the responses. Thank you
They aren not "translated" during build time, this is what is happening with you. On a node environment, when you ask for process.env it will show all environment variables available in the system, that is true. But a web application does not have access to process.env when it is executing. You need a way to translate them during build time.
To achieve that you have to use DefinePlugin. It translates anything during build time and writes a magical string where this other thing was.
Using you own example:
module.exports = {
NODE_ENV: '"production"',
BACKEND_URL: JSON.stringify(process.env.BACKEND_URL)
}
If you do this during build time, without DefinePlugin, webpack won't know what to do with it, and it is going to be a simple string.
If you use DefinePlugin:
new webpack.DefinePlugin({
"process.env.BACKEND_URL": JSON.stringify(process.env.BACKEND_URL)
});
By doing this, you are allowing webpack to translate this during build time.
Give this a shot: https://www.brandonbarnett.io/blog/2018/05/accessing-environment-variables-from-a-webpack-bundle-in-a-docker-container/
If I'm understanding your problem correctly, you're serving a webpack bundle using nginx, and trying to access an environment variable from that bundle.
Unfortunately, it doesn't quite work that way. Your JS file has no access to the environment since it's a resource that has been delivered to the client. I've proposed a solution that also delivers those env variables alongside the bundle in a separate JS file that gets created on container start.
From VueJS Docs: https://cli.vuejs.org/guide/mode-and-env.html
Using Env Variables in Client-side Code
Only variables that start with VUE_APP_ will be statically embedded into the client bundle with webpack.DefinePlugin. You can access them in your application code:
console.log(process.env.VUE_APP_SECRET)
During build, process.env.VUE_APP_SECRET will be replaced by the corresponding value. In the case of VUE_APP_SECRET=secret, it will be replaced by "secret".
So in your case, the following should do the trick. I had the same problem once in my project, which I started with vue/cli and vue create project ...
VUE_APP_BACKEND_URL=https://whatever:3000

Resources