Prevent overwriting, allow deletion.
This commit is contained in:
parent
e77e999fcb
commit
500c584918
14
Dockerfile
Normal file
14
Dockerfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
FROM 063932952339.dkr.ecr.us-west-2.amazonaws.com/alpine-nim:nim-1.6.10 AS build
|
||||||
|
MAINTAINER jonathan@jdbernard.com
|
||||||
|
|
||||||
|
COPY toclerbe.nimble /toclerbe/
|
||||||
|
COPY src /toclerbe/src
|
||||||
|
WORKDIR /toclerbe
|
||||||
|
RUN nimble build -y
|
||||||
|
|
||||||
|
FROM alpine
|
||||||
|
EXPOSE 80
|
||||||
|
|
||||||
|
COPY --from=build /toclerbe/toclerbe /
|
||||||
|
COPY ministrysuite_api.config.docker.json /ministrysuite_api.config.json
|
||||||
|
CMD ["/toclerbe", "serve"]
|
34
Makefile
Normal file
34
Makefile
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
SOURCES=$(wildcard src/*.nim)
|
||||||
|
TARGET_ENV ?= local
|
||||||
|
ECR_ACCOUNT_URL ?= 063932952339.dkr.ecr.us-west-2.amazonaws.com
|
||||||
|
VERSION ?=`git describe`
|
||||||
|
PORT ?= 8080
|
||||||
|
|
||||||
|
default: serve-docker
|
||||||
|
|
||||||
|
build: $(SOURCES)
|
||||||
|
nimble build
|
||||||
|
|
||||||
|
serve: build
|
||||||
|
TOCLERBE_PORT=$(PORT) \
|
||||||
|
TOCLERBE_API_KEYS=qwertyasdfgh \
|
||||||
|
./toclerbe urls.txt
|
||||||
|
|
||||||
|
# Build the container image.
|
||||||
|
build-image: $(SOURCES)
|
||||||
|
docker image build -t $(ECR_ACCOUNT_URL)/toclerbe:$(VERSION) .
|
||||||
|
|
||||||
|
# Push the container image to the private AWS ECR
|
||||||
|
push-image: build-image
|
||||||
|
docker push $(ECR_ACCOUNT_URL)/toclerbe:$(VERSION)
|
||||||
|
|
||||||
|
serve-docker: build-image start-postgres
|
||||||
|
docker run \
|
||||||
|
-e TOCLERBE_PORT=80 \
|
||||||
|
-e TOCLERBE_API_KEYS=qwertyasdfgh
|
||||||
|
-e "ISSUER=$(ISSUER)" \
|
||||||
|
-p 127.0.0.1:$(PORT):80/tcp \
|
||||||
|
$(ECR_ACCOUNT_URL)/toclerbe:$(VERSION)
|
||||||
|
|
||||||
|
ecr-auth:
|
||||||
|
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin $(ECR_ACCOUNT_URL)
|
Binary file not shown.
@ -11,22 +11,25 @@ type
|
|||||||
port*: int
|
port*: int
|
||||||
urls*: StringTableRef
|
urls*: StringTableRef
|
||||||
|
|
||||||
|
const CT_TXT = "text/plain"
|
||||||
|
|
||||||
proc parseUrlLine(line: string, lineNo: int): tuple[k, v: string] =
|
proc parseUrlLine(line: string, lineNo: int): tuple[k, v: string] =
|
||||||
let pair = line.split("\t")
|
let pair = line.split("\t")
|
||||||
if pair.len != 2:
|
if pair.len != 2:
|
||||||
warn "Error loading URLs file. Line #" & $lineNo &
|
raise newException(ValueError, "Error loading URLs file. Line #" &
|
||||||
" does not contain exactly two values separated by \\t."
|
$lineNo & " does not contain exactly two values separated by \\t.")
|
||||||
result = (pair[0], pair[1])
|
result = (pair[0], pair[1])
|
||||||
|
|
||||||
proc loadUrlsFile(filename: string): StringTableRef =
|
proc loadUrlsFile(filename: string): StringTableRef =
|
||||||
result = newStringTable()
|
result = newStringTable()
|
||||||
|
|
||||||
var lineNo = 0
|
if fileExists(filename):
|
||||||
for line in filename.lines:
|
var lineNo = 0
|
||||||
lineNo += 1
|
for line in filename.lines:
|
||||||
let pair = parseUrlLine(line, lineNo)
|
lineNo += 1
|
||||||
result[pair.k] = pair.v
|
let pair = parseUrlLine(line, lineNo)
|
||||||
debug "Adding: " & pair.k & " -> " & pair.v
|
result[pair.k] = pair.v
|
||||||
|
debug "Adding: " & pair.k & " -> " & pair.v
|
||||||
|
|
||||||
proc persist(cfg: ToClerbeCfg) =
|
proc persist(cfg: ToClerbeCfg) =
|
||||||
var f: File
|
var f: File
|
||||||
@ -87,7 +90,7 @@ proc serveApi(cfg: ToClerbeCfg) =
|
|||||||
routes:
|
routes:
|
||||||
|
|
||||||
options "version": sendOptionsResp(@[HttpGet])
|
options "version": sendOptionsResp(@[HttpGet])
|
||||||
get "version": resp "to.cler.be v" & TOCLERBE_VERSION
|
get "version": resp("to.cler.be v" & TOCLERBE_VERSION, CT_TXT)
|
||||||
|
|
||||||
options "api/create": sendOptionsResp(@[HttpPost])
|
options "api/create": sendOptionsResp(@[HttpPost])
|
||||||
post "api/create":
|
post "api/create":
|
||||||
@ -97,19 +100,35 @@ proc serveApi(cfg: ToClerbeCfg) =
|
|||||||
for line in request.body.splitLines:
|
for line in request.body.splitLines:
|
||||||
lineNo += 1
|
lineNo += 1
|
||||||
let pair = parseUrlLine(line, lineNo)
|
let pair = parseUrlLine(line, lineNo)
|
||||||
|
if cfg.urls.contains(pair.k):
|
||||||
|
halt(Http403, {"Content-Type": CT_TXT},
|
||||||
|
"mapping already exists for " & pair.k)
|
||||||
|
|
||||||
cfg.urls[pair.k] = pair.v
|
cfg.urls[pair.k] = pair.v
|
||||||
info "Added URL mapping: " & pair.k & " -> " & pair.v
|
info "Added URL mapping: " & pair.k & " -> " & pair.v
|
||||||
cfg.persist()
|
cfg.persist()
|
||||||
resp(Http200, "", "text/plain")
|
resp(Http200, "", CT_TXT)
|
||||||
except:
|
|
||||||
resp(Http500, {"Content-Type": "text/plain"}, getCurrentExceptionMsg())
|
|
||||||
|
|
||||||
|
except:
|
||||||
|
resp(Http500, getCurrentExceptionMsg(), CT_TXT)
|
||||||
|
|
||||||
|
options re".*": sendOptionsResp(@[HttpGet, HttpDelete])
|
||||||
get re".*":
|
get re".*":
|
||||||
debug "Look up short-url: " & request.pathInfo
|
debug "Look up short-url: " & request.pathInfo
|
||||||
if cfg.urls.contains(request.pathInfo):
|
if cfg.urls.contains(request.pathInfo):
|
||||||
resp(Http302, {"Location": cfg.urls[request.pathInfo]}, "")
|
resp(Http302, {"Location": cfg.urls[request.pathInfo]}, "")
|
||||||
else:
|
else:
|
||||||
resp(Http404, {"Content-Type": "text/plain"}, "not found")
|
resp(Http404, "not found", CT_TXT)
|
||||||
|
|
||||||
|
delete re".*":
|
||||||
|
checkAuth(cfg)
|
||||||
|
try:
|
||||||
|
cfg.urls.del(request.pathInfo)
|
||||||
|
cfg.persist()
|
||||||
|
resp(Http200, "", CT_TXT)
|
||||||
|
|
||||||
|
except:
|
||||||
|
resp(Http500, getCurrentExceptionMsg(), CT_TXT)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user