Angular (web framework): Difference between revisions
(3 intermediate revisions by the same user not shown) | |||
Line 81: | Line 81: | ||
RewriteRule ^ /index.html | RewriteRule ^ /index.html | ||
</pre> | </pre> | ||
}} | |||
===Express=== | |||
How to setup an Express server to host your Angular web application: | |||
{{ hidden | Route | | |||
First setup CSRF Protection: | |||
<syntaxhighlight lang="typescript"> | |||
this.csrfProtection = csurf({cookie: true}); | |||
this.app.use(this.csrfProtection); | |||
this.app.all( | |||
'*', | |||
(req: Request, res: Response, next: NextFunction): void => { | |||
res.cookie('XSRF-TOKEN', req.csrfToken()); | |||
next(); | |||
} | |||
); | |||
</syntaxhighlight> | |||
Then setup your routes to serve your frontend: | |||
<syntaxhighlight lang="typescript"> | |||
if (CONFIG.app.useProxy) { | |||
const myProxy = httpProxy.createProxyServer({ws: true}); | |||
console.log(`Proxying to ${CONFIG.app.appProxy}`); | |||
router.all('/*', (req: Request, res: Response, next: NextFunction) => { | |||
myProxy.web( | |||
req, | |||
res, | |||
{target: req.protocol + '://' + CONFIG.app.appProxy} | |||
); | |||
}); | |||
} else { | |||
router.all('/*', express.static(CONFIG.app.appFolder)); | |||
router.all('/*', (req: Request, res: Response, next: NextFunction) => { | |||
res.status(200).sendFile('index.html', {root: CONFIG.app.appFolder}); | |||
}); | |||
} | |||
</syntaxhighlight> | |||
If you are proxying for development, you will also need to proxy websockets: | |||
<syntaxhighlight lang="typescript> | |||
server.on( | |||
'upgrade', | |||
(request: http.IncomingMessage, socket: net.Socket, head: Buffer) => { | |||
const pathname = url.parse(request.url).pathname; | |||
if (pathname === '/backend') { | |||
this.wss.handleUpgrade(request, socket, head, ws => { | |||
this.wss.emit('connection', ws); | |||
}); | |||
} else if (CONFIG.app.useProxy) { | |||
console.log('proxying websocket'); | |||
myProxy.ws(request, socket, head, { | |||
target: 'ws://' + CONFIG.app.appProxy, | |||
}); | |||
} else { | |||
socket.destroy(); | |||
} | |||
} | |||
); | |||
</syntaxhighlight> | |||
}} | }} | ||
Line 88: | Line 149: | ||
* [https://github.com/angular/components Angular Components] | * [https://github.com/angular/components Angular Components] | ||
** [[Angular Material]] ([https://material.angular.io/ website]) | ** [[Angular Material]] ([https://material.angular.io/ website]) | ||
==Advanced Usage== | |||
===CSRF/XSRF=== | |||
See [https://angular.io/guide/http#security-xsrf-protection http#security-xsrf-protection] | |||
By default, the <code>HttpClientModule</code> will automatically reflect the <code>XSRF-TOKEN</code> cookie as <code>X-XSRF-TOKEN</code> if the following conditions are met: | |||
* <code>XSRF-TOKEN</code> is a cookie under <code>/</code> with <code>HttpOnly</code> set to false. | |||
* The outgoing request is not a <code>GET</code> or <code>HEAD</code> request. | |||
* The outgoing request path is a relative path of form <code>api/endpoint</code> or <code>//example.com/api/endpoint</code>. | |||
You can also set the name of the cookie and name of the header to something else if you prefer. | |||
===Open in new tab=== | |||
If you're making an SPA, and therefore using client-side routing with <code>routerLink</code>, your buttons and links may not have open in a new link on right click. | |||
See [https://stackoverflow.com/questions/56627500/right-click-open-in-new-tab-is-not-available-on-routerlink-withhin-a-div-tag SO] for a way to add this. | |||
===Advanced Routing=== | |||
* [https://medium.com/ngconf/routing-to-angular-material-dialogs-c3fb7231c177 Routing to Angular Material Dialogs] | |||
==Resources== | ==Resources== |