9 Commits

Author SHA1 Message Date
2b66c57f4c fix more liniting errors 2025-12-23 14:33:35 +01:00
38d3d2c442 fix liniting bugs 2025-12-23 14:30:37 +01:00
b4fa28d0c5 replace fiber with http.ServeMux 2025-12-23 14:24:04 +01:00
37c7e808ed replace the fiber framework with net/http.ServeMux 2025-12-23 13:33:05 +01:00
5a705b0af0 fix links 2025-11-05 08:59:43 +01:00
7129f644d3 fix changelog link 2025-11-05 08:47:43 +01:00
9cb5a4b800 add test dependencies, separate test ci 2025-11-03 10:43:06 +01:00
53d69b5278 add dist makefile 2025-11-03 10:01:24 +01:00
T. von Dein
a16b9e796c move to codeberg (#22) 2025-11-03 09:15:27 +01:00
30 changed files with 522 additions and 405 deletions

View File

@@ -1,56 +0,0 @@
name: build-and-test
#on: [push]
on:
pull_request:
branches:
- main
push:
branches:
- main
jobs:
build:
strategy:
matrix:
version: ['1.24']
os: [ubuntu-latest, macos-latest, windows-latest]
name: Build
runs-on: ${{ matrix.os }}
steps:
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.version }}
id: go
- name: checkout
uses: actions/checkout@v5
- name: build
run: go build
- name: test
run: make test
- name: Update coverage report
uses: ncruces/go-coverage-report@main
with:
report: true
chart: true
amend: true
if: |
matrix.os == 'ubuntu-latest' &&
github.event_name == 'push'
continue-on-error: true
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v6
with:
go-version: 1.24
- uses: actions/checkout@v5
- name: golangci-lint
uses: golangci/golangci-lint-action@v8

View File

@@ -1,34 +0,0 @@
name: build-push-image
on:
push:
tags:
- 'v*'
jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Log in to the Container registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
with:
registry: https://ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
with:
push: true
tags: ghcr.io/tlinden/anydb:${{ github.ref_name}}
- name: Build and push latest Docker image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
with:
push: true
tags: ghcr.io/tlinden/anydb:latest

View File

@@ -1,87 +0,0 @@
name: build-release
on:
push:
tags:
- "v*.*.*"
jobs:
release:
name: Build Release Assets
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version: 1.24.1
- name: Build the executables
run: ./mkrel.sh anydb ${{ github.ref_name}}
- name: List the executables
run: ls -l ./releases
- name: Upload the binaries
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref_name }}
file: ./releases/*
file_glob: true
- name: Build Changelog
id: github_release
uses: mikepenz/release-changelog-builder-action@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
mode: "PR"
configurationJson: |
{
"template": "#{{CHANGELOG}}\n\n**Full Changelog**: #{{RELEASE_DIFF}}",
"pr_template": "- #{{TITLE}} (##{{NUMBER}}) by #{{AUTHOR}}\n#{{BODY}}",
"empty_template": "- no changes",
"categories": [
{
"title": "## New Features",
"labels": ["add", "feature"]
},
{
"title": "## Bug Fixes",
"labels": ["fix", "bug", "revert"]
},
{
"title": "## Documentation Enhancements",
"labels": ["doc"]
},
{
"title": "## Refactoring Efforts",
"labels": ["refactor"]
},
{
"title": "## Miscellaneus Changes",
"labels": []
}
],
"ignore_labels": [
"duplicate", "good first issue", "help wanted", "invalid", "question", "wontfix"
],
"label_extractor": [
{
"pattern": "(.) (.+)",
"target": "$1"
},
{
"pattern": "(.) (.+)",
"target": "$1",
"on_property": "title"
}
]
}
- name: Create Release
uses: softprops/action-gh-release@v2
with:
body: ${{steps.github_release.outputs.changelog}}

69
.goreleaser.yaml Normal file
View File

@@ -0,0 +1,69 @@
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
version: 2
before:
hooks:
- go mod tidy
gitea_urls:
api: https://codeberg.org/api/v1
download: https://codeberg.org
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
- freebsd
archives:
- formats: [tar.gz]
# this name template makes the OS and Arch compatible with the results of `uname`.
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}_{{ .Tag }}
# use zip for windows archives
format_overrides:
- goos: windows
formats: [zip]
- goos: linux
formats: [tar.gz,binary]
files:
- src: "*.md"
strip_parent: true
- src: "docs/*"
strip_parent: true
- src: Makefile.dist
dst: Makefile
wrap_in_directory: true
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
groups:
- title: Improved
regexp: '^.*?(feat|add|new)(\([[:word:]]+\))??!?:.+$'
order: 0
- title: Fixed
regexp: '^.*?(bug|fix)(\([[:word:]]+\))??!?:.+$'
order: 1
- title: Changed
order: 999
release:
header: "# Release Notes"
footer: >-
---
Full Changelog: [{{ .PreviousTag }}...{{ .Tag }}](https://codeberg.org/scip/anydb/compare/{{ .PreviousTag }}...{{ .Tag }})

36
.woodpecker/build.yaml Normal file
View File

@@ -0,0 +1,36 @@
matrix:
platform:
- linux/amd64
goversion:
- 1.24
labels:
platform: ${platform}
steps:
build:
when:
event: [push]
image: golang:${goversion}
commands:
- go get
- go build
linter:
when:
event: [push]
image: golang:${goversion}
commands:
- curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.5.0
- golangci-lint --version
- golangci-lint run ./...
depends_on: [build]
test:
when:
event: [push]
image: golang:${goversion}
commands:
- go get
- go test -v -cover
depends_on: [build,linter]

32
.woodpecker/image.yaml Normal file
View File

@@ -0,0 +1,32 @@
# https://woodpecker-ci.org/plugins/docker-buildx
# enable Package unit and go to /scip/-/packages after building to link to proj
variables:
- &repo codeberg.org/${CI_REPO_OWNER}/anydb
steps:
dryrun:
image: docker.io/woodpeckerci/plugin-docker-buildx:latest
settings:
dockerfile: Dockerfile
platforms: linux/amd64
dry_run: true
repo: *repo
tags: latest
when:
event: [pull_request]
publish:
image: docker.io/woodpeckerci/plugin-docker-buildx:latest
settings:
dockerfile: Dockerfile
platforms: linux/amd64
repo: *repo
registry: codeberg.org
tags: latest,${CI_COMMIT_SHA:0:8},${CI_COMMIT_TAG}
username: ${CI_REPO_OWNER}
password:
from_secret: REGISTRY_TOKEN
when:
event: [tag]
branch: main

15
.woodpecker/release.yaml Normal file
View File

@@ -0,0 +1,15 @@
# build release
labels:
platform: linux/amd64
steps:
goreleaser:
image: goreleaser/goreleaser
when:
event: [tag]
environment:
GITEA_TOKEN:
from_secret: DEPLOY_TOKEN
commands:
- goreleaser release --clean --verbose

View File

@@ -51,11 +51,11 @@ endif
app/dbentry.pb.go: app/dbentry.proto app/dbentry.pb.go: app/dbentry.proto
protoc -I=. --go_out=app app/dbentry.proto protoc -I=. --go_out=app app/dbentry.proto
mv app/github.com/tlinden/anydb/app/dbentry.pb.go app/dbentry.pb.go mv app/codeberg.org/scip/anydb/app/dbentry.pb.go app/dbentry.pb.go
rm -rf app/github.com rm -rf app/github.com
buildlocal: buildlocal:
go build -ldflags "-X 'github.com/tlinden/anydb/cfg.VERSION=$(VERSION)'" go build -ldflags "-X 'codeberg.org/scip/anydb/cfg.VERSION=$(VERSION)'"
# binaries are being built by ci workflow on tag creation # binaries are being built by ci workflow on tag creation
release: release:
@@ -75,7 +75,7 @@ test: clean
singletest: singletest:
@echo "Call like this: ''make singletest TEST=TestPrepareColumns MOD=lib" @echo "Call like this: ''make singletest TEST=TestPrepareColumns MOD=lib"
ANYDB_PASSWORD=test go test -run $(TEST) github.com/tlinden/anydb/$(MOD) ANYDB_PASSWORD=test go test -run $(TEST) codeberg.org/scip/anydb/$(MOD)
cover-report: cover-report:
go test ./... -cover -coverprofile=coverage.out go test ./... -cover -coverprofile=coverage.out

20
Makefile.dist Normal file
View File

@@ -0,0 +1,20 @@
# -*-make-*-
.PHONY: install all
tool = rpn
PREFIX = /usr/local
UID = root
GID = 0
all:
@echo "Type 'sudo make install' to install the tool."
@echo "To change prefix, type 'sudo make install PREFIX=/opt'"
install:
install -d -o $(UID) -g $(GID) $(PREFIX)/bin
install -d -o $(UID) -g $(GID) $(PREFIX)/man/man1
install -d -o $(UID) -g $(GID) $(PREFIX)/share/doc
install -o $(UID) -g $(GID) -m 555 $(tool) $(PREFIX)/sbin/
install -o $(UID) -g $(GID) -m 444 $(tool).1 $(PREFIX)/man/man1/
install -o $(UID) -g $(GID) -m 444 *.md $(PREFIX)/share/doc/

View File

@@ -1,11 +1,10 @@
## A personal key value store ## A personal key value store
[![Actions](https://github.com/tlinden/anydb/actions/workflows/ci.yaml/badge.svg)](https://github.com/tlinden/anydb/actions) [![status-badge](https://ci.codeberg.org/api/badges/15517/status.svg)](https://ci.codeberg.org/repos/15517)
[![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://github.com/tlinden/anydb/blob/master/LICENSE) [![License](https://img.shields.io/badge/license-GPL-blue.svg)](https://codeberg.org/scip/anydb/blob/master/LICENSE)
[![Go Coverage](https://github.com/tlinden/anydb/wiki/coverage.svg)](https://raw.githack.com/wiki/tlinden/anydb/coverage.html) [![Go Report Card](https://goreportcard.com/badge/codeberg.org/scip/anydb)](https://goreportcard.com/report/codeberg.org/scip/anydb)
[![Go Report Card](https://goreportcard.com/badge/github.com/tlinden/anydb)](https://goreportcard.com/report/github.com/tlinden/anydb) [![GitHub release](https://img.shields.io/github/v/release/tlinden/anydb?color=%2300a719)](https://codeberg.org/scip/anydb/releases)
[![GitHub release](https://img.shields.io/github/v/release/tlinden/anydb?color=%2300a719)](https://github.com/TLINDEN/anydb/releases/latest) [![Documentation](https://img.shields.io/badge/manpage-documentation-blue)](https://codeberg.org/scip/anydb/raw/branch/main/anydb.pod)
[![Documentation](https://img.shields.io/badge/manpage-documentation-blue)](https://github.com/TLINDEN/anydb/blob/master/anydb.pod)
> [!CAUTION] > [!CAUTION]
> Between version 0.1.0 and version 0.2.1 deletion of keys did not work. There > Between version 0.1.0 and version 0.2.1 deletion of keys did not work. There
@@ -14,7 +13,7 @@
> upgrade to 0.2.1 and above. > upgrade to 0.2.1 and above.
> [!CAUTION] > [!CAUTION]
> Version 0.1.3 introduced a [regression](https://github.com/TLINDEN/anydb/issues/19), > Version 0.1.3 introduced a [regression](https://codeberg.org/scip/anydb/issues/19),
> which caused the encryption feature not to work correctly anymore. > which caused the encryption feature not to work correctly anymore.
> If you are using anydb 0.1.3, you are urgently advised to > If you are using anydb 0.1.3, you are urgently advised to
> upgrade to 0.2.0 > upgrade to 0.2.0
@@ -47,17 +46,17 @@ And I wrote a very similar [tool](https://www.daemon.de/projects/dbtool/) 24 yea
**anydb** can do all the things you can do with skate: **anydb** can do all the things you can do with skate:
![simple demo](https://github.com/TLINDEN/anydb/blob/main/demo/intro.gif) ![simple demo](https://codeberg.org/scip/anydb/raw/branch/main/demo/intro.gif)
However, there are more features than just that! However, there are more features than just that!
![advanced demo](https://github.com/TLINDEN/anydb/blob/main/demo/advanced.gif) ![advanced demo](https://codeberg.org/scip/anydb/raw/branch/main/demo/advanced.gif)
## Installation ## Installation
There are multiple ways to install **anydb**: There are multiple ways to install **anydb**:
- Go to the [latest release page](https://github.com/tlinden/anydb/releases/latest), - Go to the [latest release page](https://codeberg.org/scip/anydb/releases),
locate the binary for your operating system and platform. locate the binary for your operating system and platform.
Download it and put it into some directory within your `$PATH` variable. Download it and put it into some directory within your `$PATH` variable.
@@ -70,7 +69,7 @@ There are multiple ways to install **anydb**:
- You can also install from source. Issue the following commands in your shell: - You can also install from source. Issue the following commands in your shell:
```shell ```shell
git clone https://github.com/TLINDEN/anydb.git git clone https://codeberg.org/scip/anydb.git
cd anydb cd anydb
make make
sudo make install sudo make install
@@ -78,7 +77,7 @@ There are multiple ways to install **anydb**:
- Or, if you have the GO toolkit installed, just install it like this: - Or, if you have the GO toolkit installed, just install it like this:
```shell ```shell
go install github.com/tlinden/anydb@latest go install codeberg.org/scip/anydb@latest
``` ```
If you do not find a binary release for your platform, please don't If you do not find a binary release for your platform, please don't
@@ -105,14 +104,14 @@ Here, we operate in a local directory `mydb`, which we'll use as HOME
inside the docker container. anydb will store its database in inside the docker container. anydb will store its database in
`mydb/.config/anydb/default.db`. `mydb/.config/anydb/default.db`.
A list of available images is [here](https://github.com/tlinden/anydb/pkgs/container/anydb/versions?filters%5Bversion_type%5D=tagged) A list of available images is [here](https://codeberg.org/scip/anydb/pkgs/container/anydb/versions?filters%5Bversion_type%5D=tagged)
## Documentation ## Documentation
The documentation is provided as a unix man-page. It will be The documentation is provided as a unix man-page. It will be
automatically installed if you install from source. However, you can automatically installed if you install from source. However, you can
[read the man-page online](https://github.com/TLINDEN/anydb/blob/master/anydb.pod) [read the man-page online](https://codeberg.org/scip/anydb/blob/master/anydb.pod)
Or if you cloned the repository you can read it this way (perl needs Or if you cloned the repository you can read it this way (perl needs
to be installed though): `perldoc anydb.pod`. to be installed though): `perldoc anydb.pod`.
@@ -129,7 +128,7 @@ best way for me to forget to do something.
In order to report a bug, unexpected behavior, feature requests or to In order to report a bug, unexpected behavior, feature requests or to
submit a patch, please open an issue on github: submit a patch, please open an issue on github:
https://github.com/TLINDEN/anydb/issues. https://codeberg.org/scip/anydb/issues.
## Copyright and license ## Copyright and license
@@ -141,7 +140,7 @@ T.v.Dein <tom AT vondein DOT org>
## Project homepage ## Project homepage
https://github.com/TLINDEN/anydb https://codeberg.org/scip/anydb
## Copyright and License ## Copyright and License

View File

@@ -1,4 +1,4 @@
.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42)
.\" .\"
.\" Standard preamble: .\" Standard preamble:
.\" ======================================================================== .\" ========================================================================
@@ -133,7 +133,7 @@
.\" ======================================================================== .\" ========================================================================
.\" .\"
.IX Title "ANYDB 1" .IX Title "ANYDB 1"
.TH ANYDB 1 "2025-02-11" "1" "User Commands" .TH ANYDB 1 "2025-11-03" "1" "User Commands"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents. .\" way too many mistakes in technical documents.
.if n .ad l .if n .ad l
@@ -746,7 +746,7 @@ List all keys:
.IX Header "BUGS" .IX Header "BUGS"
In order to report a bug, unexpected behavior, feature requests In order to report a bug, unexpected behavior, feature requests
or to submit a patch, please open an issue on github: or to submit a patch, please open an issue on github:
<https://github.com/TLINDEN/anydb/issues>. <https://codeberg.org/scip/anydb/issues>.
.PP .PP
Please repeat the failing command with debugging enabled \f(CW\*(C`\-d\*(C'\fR and Please repeat the failing command with debugging enabled \f(CW\*(C`\-d\*(C'\fR and
include the output in the issue. include the output in the issue.

View File

@@ -569,7 +569,7 @@ Some curl example calls to the API:
Post a new key: Post a new key:
curl -X PUT localhost:8787/anydb/v1/ \ curl -X PUT localhost:8787/anydb/v1/ \
-H 'Content-Type: application/json' \ -H 'Content-Type: application/json' \
-d '{"key":"foo","val":"bar"}' -d '{"key":"foo","data":"bar"}'
Retrieve the value: Retrieve the value:
@@ -579,11 +579,16 @@ List all keys:
curl localhost:8787/anydb/v1/ curl localhost:8787/anydb/v1/
Delete an entry:
curl -s -X DELETE http://localhost:8787/anydb/v1/foo
=head1 BUGS =head1 BUGS
In order to report a bug, unexpected behavior, feature requests In order to report a bug, unexpected behavior, feature requests
or to submit a patch, please open an issue on github: or to submit a patch, please open an issue on github:
L<https://github.com/TLINDEN/anydb/issues>. L<https://codeberg.org/scip/anydb/issues>.
Please repeat the failing command with debugging enabled C<-d> and Please repeat the failing command with debugging enabled C<-d> and
include the output in the issue. include the output in the issue.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright © 2024 Thomas von Dein Copyright © 2024-2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@ type DbAttr struct {
Key string Key string
Preview string Preview string
Val []byte Val []byte
Data string // alias
Args []string Args []string
Tags []string Tags []string
File string File string
@@ -63,6 +64,12 @@ func (attr *DbAttr) ParseKV() error {
} }
} }
attr.SetPreview()
return nil
}
func (attr *DbAttr) SetPreview() {
switch { switch {
case attr.Binary: case attr.Binary:
attr.Preview = "<binary-content>" attr.Preview = "<binary-content>"
@@ -82,8 +89,6 @@ func (attr *DbAttr) ParseKV() error {
attr.Preview = string(attr.Val) attr.Preview = string(attr.Val)
} }
} }
return nil
} }
func (attr *DbAttr) GetFileValue() error { func (attr *DbAttr) GetFileValue() error {

View File

@@ -28,7 +28,7 @@ import (
"strings" "strings"
"time" "time"
common "github.com/tlinden/anydb/common" common "codeberg.org/scip/anydb/common"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"

View File

@@ -5,7 +5,7 @@ package app;
import "google/protobuf/timestamp.proto"; import "google/protobuf/timestamp.proto";
option go_package = "github.com/tlinden/anydb/app"; option go_package = "codeberg.org/scip/anydb/app";
message DbEntry { message DbEntry {
string Id = 1; string Id = 1;

View File

@@ -19,14 +19,18 @@ package cfg
import ( import (
"fmt" "fmt"
"io" "io"
"log/slog"
"os" "os"
"runtime/debug"
"codeberg.org/scip/anydb/app"
"codeberg.org/scip/anydb/common"
"github.com/lmittmann/tint"
"github.com/pelletier/go-toml" "github.com/pelletier/go-toml"
"github.com/tlinden/anydb/app" "github.com/tlinden/yadu"
"github.com/tlinden/anydb/common"
) )
var Version string = "v0.2.6" var Version string = "v0.3.0"
type BucketConfig struct { type BucketConfig struct {
Encrypt bool Encrypt bool
@@ -58,6 +62,8 @@ func (conf *Config) GetConfig(files []string) error {
} }
} }
conf.SetLogger()
return nil return nil
} }
@@ -114,3 +120,36 @@ func (conf *Config) ParseConfigFile(file string) error {
return nil return nil
} }
func (conf *Config) SetLogger() {
if conf.Debug {
buildInfo, _ := debug.ReadBuildInfo()
opts := &yadu.Options{
Level: slog.LevelDebug,
AddSource: true,
}
slog.SetLogLoggerLevel(slog.LevelDebug)
handler := yadu.NewHandler(os.Stdout, opts)
debuglogger := slog.New(handler).With(
slog.Group("program_info",
slog.Int("pid", os.Getpid()),
slog.String("go_version", buildInfo.GoVersion),
),
)
slog.SetDefault(debuglogger)
slog.Debug("parsed config", "conf", conf)
} else {
opts := &tint.Options{
Level: slog.LevelInfo,
AddSource: false,
}
handler := tint.NewHandler(os.Stderr, opts)
logger := slog.New(handler)
slog.SetDefault(logger)
}
}

View File

@@ -517,7 +517,7 @@ REST API
BUGS BUGS
In order to report a bug, unexpected behavior, feature requests or to In order to report a bug, unexpected behavior, feature requests or to
submit a patch, please open an issue on github: submit a patch, please open an issue on github:
<https://github.com/TLINDEN/anydb/issues>. <https://codeberg.org/scip/anydb/issues>.
Please repeat the failing command with debugging enabled "-d" and Please repeat the failing command with debugging enabled "-d" and
include the output in the issue. include the output in the issue.

View File

@@ -1,5 +1,5 @@
/* /*
Copyright © 2024 Thomas von Dein Copyright © 2024-2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -21,10 +21,10 @@ import (
"os" "os"
"strings" "strings"
"codeberg.org/scip/anydb/app"
"codeberg.org/scip/anydb/cfg"
"codeberg.org/scip/anydb/output"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tlinden/anydb/app"
"github.com/tlinden/anydb/cfg"
"github.com/tlinden/anydb/output"
) )
func Set(conf *cfg.Config) *cobra.Command { func Set(conf *cfg.Config) *cobra.Command {

View File

@@ -26,10 +26,10 @@ import (
"os/exec" "os/exec"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tlinden/anydb/app" "codeberg.org/scip/anydb/app"
"github.com/tlinden/anydb/cfg" "codeberg.org/scip/anydb/cfg"
"github.com/tlinden/anydb/output" "codeberg.org/scip/anydb/output"
"github.com/tlinden/anydb/rest" "codeberg.org/scip/anydb/rest"
) )
func Export(conf *cfg.Config) *cobra.Command { func Export(conf *cfg.Config) *cobra.Command {

View File

@@ -25,8 +25,8 @@ import (
"runtime/debug" "runtime/debug"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/tlinden/anydb/app" "codeberg.org/scip/anydb/app"
"github.com/tlinden/anydb/cfg" "codeberg.org/scip/anydb/cfg"
"github.com/tlinden/yadu" "github.com/tlinden/yadu"
) )

View File

@@ -177,6 +177,6 @@ Enter
Sleep 3s Sleep 3s
Enter Enter
Type "# Try it out yourself: github.com/tlinden/anydb!" Type "# Try it out yourself: codeberg.org/scip/anydb!"
Enter Enter
Sleep 4s Sleep 4s

11
go.mod
View File

@@ -1,4 +1,4 @@
module github.com/tlinden/anydb module codeberg.org/scip/anydb
go 1.24.0 go 1.24.0
@@ -6,8 +6,8 @@ toolchain go1.24.1
require ( require (
github.com/dustin/go-humanize v1.0.1 github.com/dustin/go-humanize v1.0.1
github.com/gofiber/fiber/v2 v2.52.9
github.com/inconshreveable/mousetrap v1.1.0 github.com/inconshreveable/mousetrap v1.1.0
github.com/lmittmann/tint v1.1.2
github.com/olekukonko/tablewriter v1.1.0 github.com/olekukonko/tablewriter v1.1.0
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/rogpeppe/go-internal v1.14.1 github.com/rogpeppe/go-internal v1.14.1
@@ -20,10 +20,8 @@ require (
) )
require ( require (
github.com/andybalholm/brotli v1.1.1 // indirect github.com/alecthomas/repr v0.5.2 // indirect
github.com/fatih/color v1.16.0 // indirect github.com/fatih/color v1.16.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect
@@ -31,9 +29,6 @@ require (
github.com/olekukonko/ll v0.0.9 // indirect github.com/olekukonko/ll v0.0.9 // indirect
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect
github.com/spf13/pflag v1.0.9 // indirect github.com/spf13/pflag v1.0.9 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.55.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.36.0 // indirect golang.org/x/sys v0.36.0 // indirect
golang.org/x/tools v0.26.0 // indirect golang.org/x/tools v0.26.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

20
go.sum
View File

@@ -1,5 +1,5 @@
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -7,16 +7,12 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/gofiber/fiber/v2 v2.52.9 h1:YjKl5DOiyP3j0mO61u3NTmK7or8GzzWzCFzkboyP5cw=
github.com/gofiber/fiber/v2 v2.52.9/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w=
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -46,14 +42,6 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY= github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY=
github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA= github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo= go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E= go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=

View File

@@ -24,7 +24,7 @@ import (
"runtime" "runtime"
"github.com/inconshreveable/mousetrap" "github.com/inconshreveable/mousetrap"
"github.com/tlinden/anydb/cmd" "codeberg.org/scip/anydb/cmd"
) )
func main() { func main() {

View File

@@ -21,8 +21,8 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/tlinden/anydb/app" "codeberg.org/scip/anydb/app"
"github.com/tlinden/anydb/cfg" "codeberg.org/scip/anydb/cfg"
) )
func WriteJSON(attr *app.DbAttr, conf *cfg.Config, entries app.DbEntries) error { func WriteJSON(attr *app.DbAttr, conf *cfg.Config, entries app.DbEntries) error {

View File

@@ -30,8 +30,8 @@ import (
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer" "github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw" "github.com/olekukonko/tablewriter/tw"
"github.com/tlinden/anydb/app" "codeberg.org/scip/anydb/app"
"github.com/tlinden/anydb/cfg" "codeberg.org/scip/anydb/cfg"
) )
func List(writer io.Writer, conf *cfg.Config, entries app.DbEntries) error { func List(writer io.Writer, conf *cfg.Config, entries app.DbEntries) error {

View File

@@ -25,8 +25,8 @@ import (
"reflect" "reflect"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/tlinden/anydb/app" "codeberg.org/scip/anydb/app"
"github.com/tlinden/anydb/cfg" "codeberg.org/scip/anydb/cfg"
"golang.org/x/term" "golang.org/x/term"
//"github.com/alecthomas/repr" //"github.com/alecthomas/repr"
) )

View File

@@ -1,5 +1,5 @@
/* /*
Copyright © 2024 Thomas von Dein Copyright © 2024-2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -19,9 +19,12 @@ package rest
import ( import (
//"github.com/alecthomas/repr" //"github.com/alecthomas/repr"
"github.com/gofiber/fiber/v2" "encoding/json"
"github.com/tlinden/anydb/app" "log"
"github.com/tlinden/anydb/cfg" "net/http"
"codeberg.org/scip/anydb/app"
"codeberg.org/scip/anydb/cfg"
) )
type SetContext struct { type SetContext struct {
@@ -40,101 +43,113 @@ type SingleResponse struct {
Entry *app.DbEntry Entry *app.DbEntry
} }
func RestList(c *fiber.Ctx, conf *cfg.Config) error { func RestList(resp http.ResponseWriter, req *http.Request, conf *cfg.Config) {
attr := new(app.DbAttr) attr := new(app.DbAttr)
if len(c.Body()) > 0 { err := json.NewDecoder(req.Body).Decode(&attr)
if err := c.BodyParser(attr); err != nil { if err != nil {
return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{ if err.Error() != `EOF` {
"errors": err.Error(), http.Error(resp, err.Error(), http.StatusBadRequest)
}) return
} }
} }
// get list // get list
entries, err := conf.DB.List(attr, attr.Fulltext) entries, err := conf.DB.List(attr, attr.Fulltext)
if err != nil { if err != nil {
return JsonStatus(c, fiber.StatusForbidden, JsonStatus(resp, http.StatusForbidden, "Unable to list keys: "+err.Error())
"Unable to list keys: "+err.Error()) return
} }
return c.Status(fiber.StatusOK).JSON( resp.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(resp).Encode(
ListResponse{ ListResponse{
Code: http.StatusOK,
Success: true, Success: true,
Code: fiber.StatusOK,
Entries: entries, Entries: entries,
},
)
}
func RestGet(c *fiber.Ctx, conf *cfg.Config) error {
if c.Params("key") == "" {
return JsonStatus(c, fiber.StatusForbidden,
"key not provided")
}
// get list
entry, err := conf.DB.Get(&app.DbAttr{Key: c.Params("key")})
if err != nil {
return JsonStatus(c, fiber.StatusForbidden,
"Unable to get key: "+err.Error())
}
if entry.Key == "" {
return JsonStatus(c, fiber.StatusForbidden,
"Key does not exist")
}
return c.Status(fiber.StatusOK).JSON(
SingleResponse{
Success: true,
Code: fiber.StatusOK,
Entry: entry,
},
)
}
func RestDelete(c *fiber.Ctx, conf *cfg.Config) error {
if c.Params("key") == "" {
return JsonStatus(c, fiber.StatusForbidden,
"key not provided")
}
// get list
err := conf.DB.Del(&app.DbAttr{Key: c.Params("key")})
if err != nil {
return JsonStatus(c, fiber.StatusForbidden,
"Unable to delete key: "+err.Error())
}
return c.Status(fiber.StatusOK).JSON(
Result{
Success: true,
Code: fiber.StatusOK,
Message: "key deleted",
},
)
}
func RestSet(c *fiber.Ctx, conf *cfg.Config) error {
attr := new(app.DbAttr)
if err := c.BodyParser(attr); err != nil {
return c.Status(fiber.StatusUnprocessableEntity).JSON(fiber.Map{
"errors": err.Error(),
}) })
}
err := conf.DB.Set(attr)
if err != nil { if err != nil {
return JsonStatus(c, fiber.StatusForbidden, log.Fatal(err)
"Unable to set key: "+err.Error()) }
}
func RestGet(resp http.ResponseWriter, req *http.Request, key string, conf *cfg.Config) {
if key == "" {
JsonStatus(resp, http.StatusForbidden, "key not provided")
return
} }
return c.Status(fiber.StatusOK).JSON( // get list
Result{ entry, err := conf.DB.Get(&app.DbAttr{Key: key})
if err != nil {
JsonStatus(resp, http.StatusForbidden, "Unable to get key: "+err.Error())
return
}
if entry.Key == "" {
JsonStatus(resp, http.StatusForbidden, "Key does not exist")
return
}
resp.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(resp).Encode(
SingleResponse{
Code: http.StatusOK,
Success: true, Success: true,
Code: fiber.StatusOK, Entry: entry,
}, })
)
if err != nil {
log.Fatal(err)
}
}
func RestDelete(resp http.ResponseWriter, req *http.Request, key string, conf *cfg.Config) {
if key == "" {
JsonStatus(resp, http.StatusForbidden, "key not provided")
return
}
// get list
err := conf.DB.Del(&app.DbAttr{Key: key})
if err != nil {
JsonStatus(resp, http.StatusForbidden, "Unable to delete key: "+err.Error())
return
}
JsonStatus(resp, http.StatusOK, "key deleted")
}
func RestSet(resp http.ResponseWriter, req *http.Request, conf *cfg.Config) {
attr := new(app.DbAttr)
err := json.NewDecoder(req.Body).Decode(&attr)
if err != nil {
http.Error(resp, err.Error(), http.StatusBadRequest)
return
}
// attr.Data is a string, thus the decoder doesn't expect it to be
// base64 encoded. However, internally we need []byte, therefore
// we copy a cast to .Val. We also need to setup the .Preview
// value here.
attr.Val = []byte(attr.Data)
attr.SetPreview()
err = conf.DB.Set(attr)
if err != nil {
JsonStatus(resp, http.StatusForbidden, "Unable to set key: "+err.Error())
return
}
JsonStatus(resp, http.StatusOK, "key added/updated")
}
func Home(resp http.ResponseWriter) {
_, err := resp.Write([]byte("Use the REST API on " + apiprefix + "\r\n"))
if err != nil {
log.Fatal(err)
}
} }

98
rest/log.go Normal file
View File

@@ -0,0 +1,98 @@
/*
This logging middleware is based on
https://github.com/elithrar/admission-control/blob/v0.6.3/request_logger.go
by Matt Silverlock licensed under the Apache-2.0 license.
I am using slog and added a couple of small modifications.
*/
package rest
import (
"log/slog"
"net/http"
"runtime/debug"
"time"
)
// responseWriter is a minimal wrapper for http.ResponseWriter that allows the
// written HTTP status code to be captured for logging.
type responseWriter struct {
http.ResponseWriter
status int
size int
wroteHeader bool
}
func wrapResponseWriter(w http.ResponseWriter) *responseWriter {
return &responseWriter{ResponseWriter: w}
}
func (rw *responseWriter) Status() int {
return rw.status
}
func (rw *responseWriter) Size() int {
return rw.size
}
func (rw *responseWriter) WriteHeader(code int) {
if rw.wroteHeader {
return
}
rw.status = code
rw.ResponseWriter.WriteHeader(code)
rw.wroteHeader = true
}
func (rw *responseWriter) Write(data []byte) (int, error) {
written, err := rw.ResponseWriter.Write(data)
rw.size += written
return written, err
}
// LoggingMiddleware logs the incoming HTTP request & its duration.
func LogHandler() func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(resp http.ResponseWriter, req *http.Request) {
defer func() {
if err := recover(); err != nil {
resp.WriteHeader(http.StatusInternalServerError)
slog.Info(
"internal server error",
"err", err,
"trace", string(debug.Stack()),
)
}
}()
start := time.Now()
wrapped := wrapResponseWriter(resp)
next.ServeHTTP(wrapped, req)
header := wrapped.Header()["Content-Type"]
contenttype := ""
if header == nil {
contenttype = "text/plain"
} else {
contenttype = header[0]
}
slog.Info("request",
"ip", req.RemoteAddr,
"status", wrapped.status,
"method", req.Method,
"path", req.URL.EscapedPath(),
"size", wrapped.Size(),
"content-type", contenttype,
"duration", time.Since(start),
)
}
return http.HandlerFunc(fn)
}
}

View File

@@ -1,5 +1,5 @@
/* /*
Copyright © 2024 Thomas von Dein Copyright © 2024-2025 Thomas von Dein
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -17,11 +17,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
package rest package rest
import ( import (
"github.com/gofiber/fiber/v2" "encoding/json"
"github.com/gofiber/fiber/v2/middleware/compress" "log"
"github.com/gofiber/fiber/v2/middleware/cors" "net/http"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/tlinden/anydb/cfg" "codeberg.org/scip/anydb/cfg"
) )
// used to return to the api client // used to return to the api client
@@ -31,84 +31,62 @@ type Result struct {
Code int `json:"code"` Code int `json:"code"`
} }
const apiprefix = `/anydb/v1/`
func Runserver(conf *cfg.Config, args []string) error { func Runserver(conf *cfg.Config, args []string) error {
// setup api server // setup api server
router := SetupServer(conf) mux := http.NewServeMux()
// public rest api routes // just in case someone tries to access the non-api url
api := router.Group("/anydb/v1") mux.HandleFunc("GET /{$}", func(w http.ResponseWriter, r *http.Request) {
{ Home(w)
api.Get("/", func(c *fiber.Ctx) error {
return RestList(c, conf)
}) })
api.Post("/", func(c *fiber.Ctx) error { mux.HandleFunc("GET "+apiprefix+"{$}", func(w http.ResponseWriter, r *http.Request) {
// same thing as above but allows to supply parameters, see app.Dbattr{} RestList(w, r, conf)
return RestList(c, conf)
}) })
api.Get("/:key", func(c *fiber.Ctx) error { mux.HandleFunc("POST "+apiprefix+"{$}", func(w http.ResponseWriter, r *http.Request) {
return RestGet(c, conf) RestList(w, r, conf)
}) })
api.Delete("/:key", func(c *fiber.Ctx) error { mux.HandleFunc("GET "+apiprefix+"{key}", func(w http.ResponseWriter, r *http.Request) {
return RestDelete(c, conf) key := r.PathValue("key")
RestGet(w, r, key, conf)
}) })
api.Put("/", func(c *fiber.Ctx) error { mux.HandleFunc("DELETE "+apiprefix+"{key}", func(w http.ResponseWriter, r *http.Request) {
return RestSet(c, conf) key := r.PathValue("key")
}) RestDelete(w, r, key, conf)
}
// public routes
{
router.Get("/", func(c *fiber.Ctx) error {
return c.Send([]byte("Use the REST API"))
})
}
return router.Listen(conf.Listen)
}
func SetupServer(conf *cfg.Config) *fiber.App {
// disable colors
fiber.DefaultColors = fiber.Colors{}
router := fiber.New(fiber.Config{
CaseSensitive: true,
StrictRouting: true,
Immutable: true,
ServerHeader: "anydb serve",
AppName: "anydb",
}) })
router.Use(logger.New(logger.Config{ mux.HandleFunc("PUT "+apiprefix, func(w http.ResponseWriter, r *http.Request) {
Format: "${pid} ${ip}:${port} ${status} - ${method} ${path}\n", RestSet(w, r, conf)
DisableColors: true, })
}))
router.Use(cors.New(cors.Config{ logger := LogHandler()
AllowMethods: "GET,PUT,POST,DELETE",
ExposeHeaders: "Content-Type,Accept",
}))
router.Use(compress.New(compress.Config{ return http.ListenAndServe(conf.Listen, logger(mux))
Level: compress.LevelBestSpeed,
}))
return router
} }
/* /*
Wrapper to respond with proper json status, message and code, Wrapper to respond with proper json status, message and code,
shall be prepared and called by the handlers directly. shall be prepared and called by the handlers directly.
*/ */
func JsonStatus(c *fiber.Ctx, code int, msg string) error { func JsonStatus(resp http.ResponseWriter, code int, msg string) {
success := code == fiber.StatusOK success := code == http.StatusOK
return c.Status(code).JSON(Result{ resp.Header().Set("Content-Type", "application/json")
resp.WriteHeader(code)
err := json.NewEncoder(resp).Encode(
Result{
Code: code, Code: code,
Message: msg, Message: msg,
Success: success, Success: success,
}) })
if err != nil {
log.Fatal(err)
}
} }