Hello, I've tried deploying a trivial app to Heroku.
I've used the Heroku Buildpack for Nim: https://github.com/vic/heroku-buildpack-nim
On my local machine, Jester serves static files (css, ico, etc.) without a problem.
I can deploy the app to Heroku. But Jester doesn't serve the static files on Heroku (403: Forbidden).
Static files are readable by others (https://github.com/dom96/jester#static-files).
Deploy here: https://ancient-scrubland-31142.herokuapp.com/
Project structure:
.
├── nim_heroku.nimble
├── Procfile
├── src
│ ├── nim_heroku
│ ├── nim_heroku.nim
│ └── views
│ └── general.nim
├── static_dir
│ ├── favicon.ico
│ └── style.css
└── tags
3 directories, 8 files
Bin file (src/nim_heroku.nim):
import jester, asyncdispatch, os, strutils
import views/general
var settings = newSettings()
if existsEnv("PORT"):
settings.port = Port(parseInt(getEnv("PORT")))
settings.staticDir = "./static_dir"
routes:
get "/":
resp renderMain()
runForever()
View file/HTML file (src/views/general.nim):
#? stdtmpl(subsChar = '$', metaChar = '#')
#
#proc renderMain*(): string =
# result = ""
<!DOCTYPE html>
<html>
<head>
<title>Nim Heroku Test</title>
<link rel="stylesheet" href="https://unpkg.com/modern-css-reset/dist/reset.min.css" />
<link rel="stylesheet" type="text/css" href="style.css">
<link rel="shortcut icon" href="favicon.ico">
</head>
<body>
<div class="center text-center">
<div class="[ flow ]">
<p>Hello World</p>
<p>This is a test</p>
</div>
</div>
</body>
</html>
#end proc
Thanks for your help.
You can use a combination of
https://nim-lang.org/docs/oswalkdir.html
to locate the files and
https://nim-lang.org/docs/system.html#staticRead%2Cstring
to store the contents in a table.
Connecting this to the router should not be that hard.
@aredirect and @hqm42: Thank you for your help.
After some trial and error, I came up with a solution thanks to your pointers.
a) Add nimassets >= 0.1.0 to your nimble file. Example (nim_heroku.nimble):
# Package
version = "0.1.0"
author = "sbr"
description = "nim-heroku"
license = "MIT"
srcDir = "src"
bin = @["nim_heroku"]
skipext = @["nim"]
# Dependencies
requires "nim >= 1.0.0", "jester >= 0.4.3", "nimassets >= 0.1.0"
b) In the commandline, create the asset file. My assets are in the ./static_dir folder:
nimassets -d=static_dir -o= src/views/assetsfile.nim
c) Import the asset file, get the asset and add it directly to the HTML as a <style> HTML tag (src/views/general.him):
#? stdtmpl(subsChar = '$', metaChar = '#')
#import assetsfile
#
#let css = assetsFile.getAsset("static_dir/style.css")
#
#proc renderMain*(): string =
# result = ""
<!DOCTYPE html>
<html>
<head>
<title>Nim Heroku Test</title>
<link rel="stylesheet" href="https://unpkg.com/modern-css-reset/dist/reset.min.css" />
<style type="text/css">
${css}
</style>
<link rel="shortcut icon" href="favicon.ico">
</head>
<body>
<div class="center text-center">
<div class="[ flow ]">
<p>Hello World</p>
<p>This is a test</p>
</div>
</div>
</body>
</html>
#end proc
a) Use os.walkdir to find the ico file. I created a separate file for this functionality: src/views/static_assets.nim:
import os, sequtils, re
var filepaths: seq[string]
for kind, path in walkdir("./static_dir/"):
filepaths.add(path)
let icoFile = filter(filepaths, proc (x: string): bool =
contains(x, re".ico"))[0]
let ico* = readFile(icoFile)
b) Import ico and serve it with jester directly under the path /favicon.ico:
import jester, asyncdispatch, os, strutils
import views/general, views/static_assets
var settings = newSettings()
settings.staticDir = "./static_dir"
if existsEnv("PORT"):
settings.port = Port(parseInt(getEnv("PORT")))
template corsResp(code, message: untyped): untyped =
mixin resp
resp code, {"Access-Control-Allow-Origin": "*"}, message
routes:
get "/":
corsResp(Http200, renderMain())
get "/favicon.ico":
corsResp(Http200, ico)
runForever()
Project structure:
.
├── nim_heroku.nimble
├── Procfile
├── src
│ ├── nim_heroku
│ ├── nim_heroku.nim
│ └── views
│ ├── assetsfile.nim
│ ├── general.nim
│ ├── static_assets
│ └── static_assets.nim
├── static_dir
│ ├── favicon.ico
│ └── style.css
└── tags
3 directories, 11 files