How to set up remix with aws cdk - javascript

I’m learning remix and trying to set up a remix project that uses aws cdk to do the server.
I have found a GitHub example here: https://github.com/ajhaining/remix-cloudfront-cdk-example
But it doesn’t really explain how or what’s going on / how to do this from scratch. If anyone could help explain how to set this up it would be a great help!

In the solution you referenced this person is using AWS CDK to deploy a front-end and back-end solution that uses the Remix framework.
In case you are unfamiliar with CDK: AWS CDK allows you to write code describing your AWS infrastructure for deployment to AWS i.e infrastructure as code.
They are using the following AWS infrastructure:
An AWS S3 bucket for storing static files (front end bundles including assets like css etched )
AWS Lambda using Cloudfront Lambda#Edge (the backend used to do server side rendering)
AWS Cloudfront as a CDN. This routes the traffic to the correct "origin" (for front end assets or server side rendering)
The whole "stack" is described in cdk-remix-app-stack.ts.
Here they describe where the source of the AWS Lambda function to do server side rendering:
const edgeFn = new NodejsFunction(this, "EdgeFn", {
currentVersionOptions: {
removalPolicy: RemovalPolicy.DESTROY,
},
entry: "server/index.ts",
logRetention: RetentionDays.THREE_DAYS,
memorySize: 1024,
timeout: Duration.seconds(10),
});
Here they describe where the source for the front-end assets is to be stored in s3:
new BucketDeployment(this, "AssetsDeployment", {
destinationBucket: assetsBucket,
distribution,
prune: true,
sources: [Source.asset("public")],
cacheControl: [
CacheControl.maxAge(Duration.days(365)),
CacheControl.sMaxAge(Duration.days(365)),
],
});
This bit is a bit more complicated, here they configure the CDN to point the distribution to the specific origins (s3 for front-end or lambda for back-end rendering)
const distribution = new Distribution(this, "Distribution", {
defaultBehavior: {
allowedMethods: AllowedMethods.ALLOW_ALL,
cachePolicy: CachePolicy.CACHING_DISABLED,
compress: true,
edgeLambdas: [
{
eventType: LambdaEdgeEventType.ORIGIN_REQUEST,
functionVersion: edgeFn.currentVersion,
includeBody: true,
},
],
origin: assetsBucketS3Origin,
originRequestPolicy: new OriginRequestPolicy(
this,
"OriginRequestPolicy",
{
headerBehavior: OriginRequestHeaderBehavior.all(),
queryStringBehavior: OriginRequestQueryStringBehavior.all(),
cookieBehavior: OriginRequestCookieBehavior.all(),
}
),
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
additionalBehaviors: {
"build/*": {
allowedMethods: AllowedMethods.ALLOW_GET_HEAD,
cachePolicy: CachePolicy.CACHING_OPTIMIZED,
compress: true,
origin: assetsBucketS3Origin,
viewerProtocolPolicy: ViewerProtocolPolicy.REDIRECT_TO_HTTPS,
},
},
});

Related

Browser-sync - proxy a domain gets HTTP error 403 - you don't have authorization to view this page

I run a gulp task using NodeJS module browser-sync as below.
=== File gulpfile.js ===
let browserSync = require('browser-sync').create();
gulp.task('browser-sync', function(){
browserSync.init( {
open: true,
injectChanges: true,
proxy: 'https://generalgulp.devsunset',
host: '192.168.1.76',
serveStatic: ['.'],
https: {
key: 'C:\\WebProjects\\GeneralGulp\\resources\\certificates\\server-generalgulp.key',
cert: 'C:\\WebProjects\\GeneralGulp\\resources\\certificates\\server-generalgulp.crt'
}
});
});
=== ===
My local project information is as below (I use latest up to current post date):
Node version: 17.1.0
NPM versions: 8.1.3
gulp: 4.0.2
NPM module browser-sync: 2.27.7
I run the browser-sync task. The output looks good.
==>
Using gulpfile C:\WebProjects\GeneralGulp\gulpfile.js
[Browsersync] Starting 'browser-sync'...
[Browsersync] Proxying: https://generalgulp.devsunset
Access URLs:
Local: https://localhost:3000
External: https://192.168.1.76:3000
UI: http://localhost:3001
UI External: http://localhost:3001
==>
I already add the SSL certificate for this domain to trusted root. I also have DNS records pointing from this domain ( https://generalgulp.devsunset ) - IP addresses ( 127.0.0.1 & 192.168.1.76)
I can access the site from both local & external address.
However, when I try to access the local resources using proxied domain ( https://generalgulp.devsunset
) , it gets an HTTP 403 :
Access to <my_custom_domain> was denied. You are not authorize to
view this page
I suppose when running my gulp "browser-sync" task, it will translate the custom domain to the https://localhost:3000 or https://192.168.1.76:3000
I have followed exactly the documents of https://browsersync.io/docs . I have also made an attempt with all solutions I could find. Those solutions led me to the gulp task that I wrote at the beginning.
I would appreciate if you can suggest me which things I should do further to troubleshoot why does my browser-sync cannot “proxy” my domain? Is there any parameter missing in my Gulp task?
Thanks !
I have modified the "proxy" parameter as below and it works when i access the proxied domain with given port:
(for my case is http(s)://generalgulp.devsunset:3000 )
`gulp.task('browser-sync', function(){
browserSync.init( {
open: true,
injectChanges: true,
proxy: 'generalgulp.devsunset',
host: '192.168.1.76',
serveStatic: ['.'],
https: {
key: 'C:\\WebProjects\\GeneralGulp\\resources\\certificates\\server-generalgulp.key',
cert: 'C:\\WebProjects\\GeneralGulp\\resources\\certificates\\server-generalgulp.crt'
}
});
});
`
This is a temporary acceptable solution regarding to the current question scope.
However, What i expect is the browser-sync will auto-forward traffic from custom domain ( http(s)://generalgulp.devsunset ) to : ( http://192.168.1.76:3000 ).
Does browser-sync allow users to do it ?

WebAuthn Relaying Party ID for various Setups

I have an Angular 11 Project, which implements a WebAuthn registration. The backend is SpringBoot 2.4
WebAuthn Login should work in two parts of the project, the "main" and the "viewer"
The domain setup is rather complicated:
Main Project
Urls
Local: https://localhost:4202
Staging: https://company.com (local Kubernetes Server)
Prod: https://company-project.com
Viewer Project
Urls
Local: https://localhost:4200
Staging: https://viewer.develop.plattform.intra.company.com (local Kubernetes Server)
Prod: https://viewer.company-project.com
Code
environment.ts
prodUrls: ['company-project.com'],
webauthn: {
name: "Company DEV",
rpId: "localhost"
}
environment.prod.ts (replace in build)
prodUrls: ['company-project.com'],
webauthn: {
name: "Company Prod",
rpId: "plattform.intra.company.com" // gets overridden by values in "prodUrls"
}
webauthn.service.ts
private _getRelyingPartyInfo(): RelyingParty {
let rpId = environment.webauthn.rpId;
/**
* Check if the Hostname matches one of our Prod Hostnames
* and use this instead
*/
environment.prodUrls.forEach((url, index) => {
if (location.hostname.indexOf(url) > -1) {
rpId = environment.prodUrls[index];
}
});
const rp = {
id: rpId,
name: environment.webauthn.name
};
return rp;
}
The Issues
It works locally, using the rpId localhost (both Backend and Frontend locally)
It does NOT work on staging --> Backend throws
WebAuthnException message: rpIdHash doesn't match the hash of preconfigured rpId.
It should work on Prod using company-project.com as rpId (scared to deploy as it does not work on staging)
What I tried
For staging, I changed the rpId to develop.plattform.intra.company.com and I can register and login in "main". Logging in on "viewer" throws an error as well
The spec is not very specific about what should work: https://www.w3.org/TR/webauthn/#relying-party-identifier, it only says what shouldn't work. I assume, that the multiple subdomains complicate things on staging?
What would be the correct rpId for staging and is the assumption that company-project.com as rpId should work on prod correct?
For staging, I changed the rpId to develop.plattform.intra.company.com and I can register and login in "main". Logging in on "viewer" throws an error as well
What's your code to get the assertion? You might also be running into this other question. You need to set the get assertion RP ID to the same RP ID used for registration. If you don't, it will default to the origin, which for your subdomain will be different.

aws-serverless-express with serverless-offline stage breaks routing

I'm using serverless package with:
- aws-serverless-express
- serverless-offline
when I'm running sls offline
I get everything to run properly but the paths I get are:
ANY | http://localhost:3001/dev/
ANY | http://localhost:3001/dev/{proxy+}
serverless.yaml
is
functions:
app:
handler: src/lambda.handler
events:
- http:
path: /
method: ANY
cors: true
- http:
path: /{proxy+}
method: ANY
cors: true
I know I have "stage" env I can set to change
but my express routes looking for it:
//this wont work
app.get('/r', (req, res) => {
res.send('ready');
})
//this will work
app.get('/dev/r', (req, res) => {
res.send('ready');
})
But in production or if I use any other "stage" my routes won't work if I don't prefix them with the stage.
Any ideas?
Thanks
Based on the docs:
sls offline --noPrependStageInUrl
should work for you
or via config:
custom:
serverless-offline:
noPrependStageInUrl: true
Available Cli options:
--apiKey Defines the API key value to be used for endpoints marked as private Defaults to a random hash.
--corsAllowHeaders Used as default Access-Control-Allow-Headers header value for responses. Delimit multiple values with commas. Default: 'accept,content-type,x-api-key'
--corsAllowOrigin Used as default Access-Control-Allow-Origin header value for responses. Delimit multiple values with commas. Default: '*'
--corsDisallowCredentials When provided, the default Access-Control-Allow-Credentials header value will be passed as 'false'. Default: true
--corsExposedHeaders Used as additional Access-Control-Exposed-Headers header value for responses. Delimit multiple values with commas. Default: 'WWW-Authenticate,Server-Authorization'
--disableCookieValidation Used to disable cookie-validation on hapi.js-server
--enforceSecureCookies Enforce secure cookies
--hideStackTraces Hide the stack trace on lambda failure. Default: false
--host -o Host name to listen on. Default: localhost
--httpPort Http port to listen on. Default: 3000
--httpsProtocol -H To enable HTTPS, specify directory (relative to your cwd, typically your project dir) for both cert.pem and key.pem files
--ignoreJWTSignature When using HttpApi with a JWT authorizer, don't check the signature of the JWT token. This should only be used for local development.
--lambdaPort Lambda http port to listen on. Default: 3002
--noPrependStageInUrl Don't prepend http routes with the stage.
--noAuth Turns off all authorizers
--noTimeout -t Disables the timeout feature.
--prefix -p Adds a prefix to every path, to send your requests to http://localhost:3000/[prefix]/[your_path] instead. Default: ''
--printOutput Turns on logging of your lambda outputs in the terminal.
--resourceRoutes Turns on loading of your HTTP proxy settings from serverless.yml
--useChildProcesses Run handlers in a child process
--useWorkerThreads Uses worker threads for handlers. Requires node.js v11.7.0 or higher
--websocketPort WebSocket port to listen on. Default: 3001
--webSocketHardTimeout Set WebSocket hard timeout in seconds to reproduce AWS limits (https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#apigateway-execution-service-websocket-limits-table). Default: 7200 (2 hours)
--webSocketIdleTimeout Set WebSocket idle timeout in seconds to reproduce AWS limits (https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#apigateway-execution-service-websocket-limits-table). Default: 600 (10 minutes)
--useDocker Run handlers in a docker container.
--layersDir The directory layers should be stored in. Default: ${codeDir}/.serverless-offline/layers'
--dockerReadOnly Marks if the docker code layer should be read only. Default: true
--allowCache Allows the code of lambda functions to cache if supported.

Re-stream RTSP from IP cam with Node Media Server to http/ws and display it with html

Goal
My goal is to display my IP cam's RTSP-output stream on a standard HTML-page (html5 + css3 + vanilla javascript, no magic = no plugins). The HTML-page should be hosted in a NGINX web server on my Raspberry Pi.
My equipment
The setup I am using is a Raspberry Pi 3 B+ with Rasbian OS, Node.js and Node-Media-Server package, NGINX (but I do not believe that NGINX is important for my problem? I have not made any config for the Node-Media-Server in it anyway.) An IP-camera, and a browser.
What I have tried
The readme in the Node-Media-Server-project is detailed and there is a tutorial describing almost exactly what I want to do. Specifically, there is a markup example on how the live stream could be accessed:
<html>
<head>
<title>Camera</title>
</head>
<body>
<script src="https://cdn.bootcss.com/flv.js/1.4.0/flv.min.js"></script>
<video id="videoElement"></video>
<script>
if (flvjs.isSupported()) {
var videoElement = document.getElementById('videoElement');
var flvPlayer = flvjs.createPlayer({
type: 'flv',
url: 'http://localhost:8000/live/uterum.flv'
});
flvPlayer.attachMediaElement(videoElement);
flvPlayer.load();
flvPlayer.play();
}
</script>
</body>
</html>
This is how I start the media server on my Raspberry PI, kommandoran-mediaserver.js:
const { NodeMediaServer } = require('node-media-server');
const config = {
logType: 3, // 3 - Log everything (debug)
rtmp: {
port: 1935,
chunk_size: 60000,
gop_cache: true,
ping: 60,
ping_timeout: 30
},
http: {
port: 8000,
allow_origin: '*'
},
relay: {
ffmpeg: '/usr/local/bin/ffmpeg',
tasks: [
{
app: 'cctv',
mode: 'static',
edge: 'rtsp://<USER>:<PASSWORD>#10.0.0.111/live1.sdp',
name: 'uterum',
rtsp_transport : 'tcp' //['udp', 'tcp', 'udp_multicast', 'http']
}
]
}
};
var nms = new NodeMediaServer(config)
nms.run();
My problem and question
When I try to view camera.html (see markup above) via the Chromium browser on Raspberry Pi (i.e. local host), nothing is displayed. In the Chromium debug inspector there are no javascript errors, but I get this:
GET http://localhost:8000/live/uterum.flv net::ERR_EMPTY_RESPONSE
Here is a screenshot from the node terminal:
The red area illustrates the output when I try to make a request to http://localhost:8000/live/uterum.flv.
I suppose I try to reach the wrong endpoint but which is correct? The documentation states http://localhost:8000/live/STREAM_NAME.flv. What is "STREAM_NAME" in my case?
As you can see from the configuration, your RTSP stream is pushed to the ‘cctv’ application.
So your playback address should be:
rtmp://localhost/cctv/uterum
or
http://localhost:8000/cctv/uterum.flv

ng-lb command in StrongLoop fails when using local-storage-connector

Dear Strongloop community
I am following the example provided by loopback for evaluating local-storage data store.
It works fine and I can use the rest API to create and retrieve files from the local file system (used as a data source).
I had to used "$ npm install loopback-component-storage --save".
the datasource defined in datasource.json is:
{
"db": {
"name": "db",
"connector": "memory"
},
"localFileSystemStorage": {
"name": "localFileSystemStorage",
"connector": "loopback-component-storage",
"provider": "filesystem",
"root": "./property_data"
}
}
the ./property_data directory is where all the data is stored. (relative to the project directory) and I can access it through rest with no issues.
Next I was trying to generate Angular service component so I can connect to the loopback server using Angular application. So inside the client directory I executed:
../example-2.0/client$ lb-ng ../server/server.js js/lb-services.js
and it failed:
/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/providers/filesystem/index.js:25
throw new Error('FileSystemProvider: Path does not exist: ' + this.root);
^
Error: FileSystemProvider: Path does not exist: ./server/storage
at new FileSystemProvider (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/providers/filesystem/index.js:25:11)
at Object.module.exports.createClient (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/providers/filesystem/index.js:17:10)
at Object.createClient (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/factory.js:86:18)
at new StorageService (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/storage-service.js:29:25)
at Object.exports.initialize (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-component-storage/lib/storage-connector.js:12:19)
at DataSource.setup (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-datasource-juggler/lib/datasource.js:332:17)
at new DataSource (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback-datasource-juggler/lib/datasource.js:109:8)
at Registry.createDataSource (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback/lib/registry.js:349:12)
at dataSourcesFromConfig (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback/lib/application.js:415:19)
at EventEmitter.app.dataSource (/home/eval/projects/loopback-component-storage/example-2.0/node_modules/loopback/lib/application.js:222:12)
Am I missing something?
I could really use some help here.
Thanks
In datasource.json file you have provided the relative path ./property_data with respect to /server folder.
Thus you need to call any method from that folder only.
Now when you are running it through the server then you are running it from /server folder thats why it runs without an issue but for angular Sdk generation you are doing it from client/ folder. Thus its genetating Path does not exist error.
Thus the correct syntax would be:
../example-2.0/server$ lb-ng server.js ../client/js/lb-services.js

Categories

Resources