diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a64f476 --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a6f2a40 --- /dev/null +++ b/Makefile @@ -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) diff --git a/src/private/.cliconstants.nim.swp b/src/private/.cliconstants.nim.swp deleted file mode 100644 index 7e2ed2d..0000000 Binary files a/src/private/.cliconstants.nim.swp and /dev/null differ diff --git a/src/toclerbe.nim b/src/toclerbe.nim index 94b08bd..00c4923 100644 --- a/src/toclerbe.nim +++ b/src/toclerbe.nim @@ -11,22 +11,25 @@ type port*: int urls*: StringTableRef +const CT_TXT = "text/plain" + proc parseUrlLine(line: string, lineNo: int): tuple[k, v: string] = let pair = line.split("\t") if pair.len != 2: - warn "Error loading URLs file. Line #" & $lineNo & - " does not contain exactly two values separated by \\t." + raise newException(ValueError, "Error loading URLs file. Line #" & + $lineNo & " does not contain exactly two values separated by \\t.") result = (pair[0], pair[1]) proc loadUrlsFile(filename: string): StringTableRef = result = newStringTable() - var lineNo = 0 - for line in filename.lines: - lineNo += 1 - let pair = parseUrlLine(line, lineNo) - result[pair.k] = pair.v - debug "Adding: " & pair.k & " -> " & pair.v + if fileExists(filename): + var lineNo = 0 + for line in filename.lines: + lineNo += 1 + let pair = parseUrlLine(line, lineNo) + result[pair.k] = pair.v + debug "Adding: " & pair.k & " -> " & pair.v proc persist(cfg: ToClerbeCfg) = var f: File @@ -87,7 +90,7 @@ proc serveApi(cfg: ToClerbeCfg) = routes: 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]) post "api/create": @@ -97,19 +100,35 @@ proc serveApi(cfg: ToClerbeCfg) = for line in request.body.splitLines: lineNo += 1 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 info "Added URL mapping: " & pair.k & " -> " & pair.v cfg.persist() - resp(Http200, "", "text/plain") - except: - resp(Http500, {"Content-Type": "text/plain"}, getCurrentExceptionMsg()) + resp(Http200, "", CT_TXT) + except: + resp(Http500, getCurrentExceptionMsg(), CT_TXT) + + options re".*": sendOptionsResp(@[HttpGet, HttpDelete]) get re".*": debug "Look up short-url: " & request.pathInfo if cfg.urls.contains(request.pathInfo): resp(Http302, {"Location": cfg.urls[request.pathInfo]}, "") 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: