labstack / armor Goto Github PK
View Code? Open in Web Editor NEWUncomplicated, modern HTTP server
Home Page: https://armor.labstack.com
License: MIT License
Uncomplicated, modern HTTP server
Home Page: https://armor.labstack.com
License: MIT License
Also update https://hub.docker.com/r/labstack/armor/
Hey! This looks super cool, and I can get it to work fine with non privileged ports, but get fails when trying to use the LetsEncrypt support. I tried to use a slightly modded config from your README.md, but admittedly I may be trying stuff I shouldnt?
I tried to run the following config using
$ sudo armor -c /tmp/armor.json
and get this fail:
{"time":"2016-09-30T15:53:26-03:00","level":"FATAL","prefix":"armor","file":"asm_amd64.s","line":"2086","message":"open : no such file or directory"}
Here's my config:
{
"address": ":443",
"tls": {
"auto": true
},
"plugins": {
"remove-trailing-slash": {
"redirect_code": 301
},
"logger": {},
"gzip": {}
},
"hosts": {
"super.ez.com": {
"plugins": {
"cors": {},
"proxy": {
"targets": [{
"url": "http://api.ls"
}]
}
}
},
"test.ez.com": {
"plugins": {
"non-www-redirect": {},
"static": {
"root": ".",
"html5": true
}
}
},
"how.com": {
"plugins": {
"static": {
"root": "."
}
}
}
}
}
Other than this, I think it'd be a good idea to:
sudo
is required to run this on ports 80/443Thanks a ton again!
Plugins data stored in postgresql database, but documentation missing.
Panic called when settings not initializated.
When I have in config.json:
{
"address": ":80",
"tls": {
"auto": false,
"cache_file": ""
},
"plugins": [{
"name": "logger"
}
],
"hosts": {
"test1.dev": {
"plugins": [{
"name": "static",
"root": "www/test1",
"html5": false,
"browse": false
}
]
},
"test2.dev": {
"plugins": [{
"name": "static",
"root": "www/test2"
}
]
}
}
}
Javascript files aren't sent to browser. Instead, I receive content from index.html
Request:
GET http://test2.dev/js/jquery.js HTTP/1.1
Host: test2.dev
Proxy-Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36
Accept: */*
Referer: http://test2.dev/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,de-DE;q=0.6,de;q=0.4,sr;q=0.2,hr;q=0.2,bs;q=0.2,sl;q=0.2
Response:
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 10635
Content-Type: text/html; charset=utf-8
Last-Modified: Wed, 16 Nov 2016 09:56:21 GMT
Server: armor/0.2.3
Date: Wed, 16 Nov 2016 10:39:41 GMT
Proxy-Connection: Keep-alive
Also for css files I receive Content-Type: text/html instead of text/css
Would be interesting to have some banchmarks on different platforms and against other http servers.
I may be wrong, but it seems like the plugin expansion code in http.go does not agree with the structs:
These are the structs,
Host struct {
CertFile string `json:"cert_file"`
KeyFile string `json:"key_file"`
Plugins map[string]interface{} `json:"plugins"`
Paths map[string]*Path `json:"paths"`
Echo *echo.Echo `json:"-"`
}
Path struct {
Plugins map[string]interface{} `json:"plugins"`
}
Host and Path have plugins. Then the correct parser should look like this:
// Host plugins
for name, host := range a.Hosts {
host.Echo = echo.New()
for name, pg := range host.Plugins {
...
} //<--- close host plugins here
// Path plugins
for name, path := range host.Paths {
g := host.Echo.Group(name)
for name, pg := range path.Plugins {
....
}
} //<-- close path plugins outside host plugins
}
Then the configuration like below can be parsed correctly.
{
"address": ":8080",
"plugins": {
"logger": {},
"static": {
"browse": true,
"root": "."
}
},
"hosts": {
"skyfall1": {
"plugins": {
"cors": {}
}
},
"skyfall2": {
"plugins": {
"cors": {}
},
"paths": {
"/api": {
"plugins": {
"gzip": {}
}
}
}
}
}
}
Thoughts?
Recently I was trying to put together a docker container (based on labstack/armor:0.4.14
) for several static sites, but no matter what I did, the hosts sections didn't seem to be getting read:
Simplified config:
address: :80
plugins:
- name: logger
- name: remove-trailing-slash
redirect_code: 301
hosts:
dragonpaw.org:
paths:
"/":
plugins:
- name: static
root: "/"
browse: true
Using httpie to test:
$ http http://localhost:80/ Host:dragonpaw.org --verbose
GET / HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: dragonpaw.org
User-Agent: HTTPie/0.9.8
HTTP/1.1 404 Not Found
Content-Length: 24
Content-Type: application/json; charset=UTF-8
Date: Sat, 28 Mar 2020 23:47:28 GMT
Server: armor/0.4.14
{
"message": "Not Found"
}
And the same on the console:
{"time":"2020-03-28T23:47:28.977242512Z","id":"","remote_ip":"172.18.0.1","host":"dragonpaw.org","method":"GET","uri":"/","user_agent":"HTTPie/0.9.8","status":404,"error":"code=404, message=Not Found","latency":28600,"latency_human":"28.6µs","bytes_in":0,"bytes_out":24}
The hostname matches what's in the config, and a browseable / shouldn't give a 404, no matter what.
So what am I missing?
Suggest to plan some kind of Health check in Proxy Plugin.
It has balance feature, but it will be nice to fallback to some url when proxy is down(ping or non 200 code for spec url) and when we have many upstream servers - exclude host from balance algoritm.
What do you think about?
Is it possible to set
"tls": {
"auto": true
}
per host?
Maybe I don't wish automatic certificates for some host.
I have issue, that after some time, Armor won't issue TLS certificate for newly entered site in config.json.
Only way to get around this issue is to completely delete cache_tls file, and to start again.
Another problem is, that I don't see that error in my Armor log file.
I am on Windows, and I am calling Armor from BAT file like so:
armor -c config.json >> armor.log
And this is working perfectly, but TLS error messages were not written into file. I see those messages only when I run armor.exe in terminal window:
⇛ https server started on
2016/11/17 11:27:42 http: TLS handshake error from 72.66.115.14:52280: unknown host
2016/11/17 11:27:45 http: TLS handshake error from 72.66.115.14:58976: unknown host
2016/11/17 11:27:45 http: TLS handshake error from 72.66.115.14:58977: unknown host)
But in my armor.log I don't see those messages, only JSON log lines are showed:
{"time":"2016-11-17T11:29:42+01:00","remote_ip":"192.168.1.3","host":"","method":"GET","uri":"timeline","status":200, "latency":2131000,"latency_human":"2.131s","bytes_in":0,"bytes_out":86578}
{"time":"2016-11-17T11:29:42+01:00","remote_ip":"192.168.1.3","host":"","method":"GET","uri":"chrome.ico","status":200, "latency":55000,"latency_human":"55ms","bytes_in":0,"bytes_out":3638}
Looking at the git commit history, I found that the sync pool of the gzip writer was removed. The reason is to fix the issue here: #13. But I still don't understand the reason for this deletion. I guess tha Is it because there is no way to return an error when using sync pool?
the removed code:
func gzipPool(config GzipConfig) sync.Pool {
return sync.Pool{
New: func() interface{} {
// can not return error here
w, _ := gzip.NewWriterLevel(ioutil.Discard, config.Level)
return w
},
}
}
Got these errors while opening my site for the first time:
016/10/31 20:50:54 [INFO] acme: Registering account for
2016/10/31 20:50:58 [INFO][snro.worksinmagic.com] acme: Obtaining bundled SAN certificate
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0xc8 pc=0x6b8f43]
goroutine 37 [running]:
panic(0x75b740, 0xc42000e0e0)
/home/dida/go/src/runtime/panic.go:500 +0x1a1
github.com/labstack/armor/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme.(*Client).getChallenges.func1(0xc4204b0bd0, 0xc4204b5560, 0xc4204b5500, 0xc4200d1960, 0x15)
/home/dida/lib/src/github.com/labstack/armor/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/client.go:406 +0x193
created by github.com/labstack/armor/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme.(*Client).getChallenges
/home/dida/lib/src/github.com/labstack/armor/vendor/github.com/rsc/letsencrypt/vendor/github.com/xenolf/lego/acme/client.go:419 +0x113
According to Repology, packages only exist for Homebrew, Linuxbrew, and Scoop -- and one of those is outdated. The BlackArch package there is for an unrelated tool.
Can the developers please contribute some packages, at least for one or two ports-like systems like Arch and Alpine, which would greatly assist others in the creation of other more-involved package types?
I haven't used armor yet, so am not familiar with -- for example -- what configuration directories and files it expects to be present. But here is a jump start for an Arch PKGBUILD:
pkgname=armor
pkgver=0.4.13
pkgrel=1
pkgdesc="Uncomplicated, modern HTTP server"
arch=('i686' 'x86_64')
url="https://github.com/labstack/armor"
license=('MIT')
makedepends=(go)
source=(${pkgname}-${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz)
sha256sums=('1e80b70c2fa245800594f3ef7b6bb14d2af4fda2a8622d3c8a0a28f9ef6c4629')
build() {
cd ${srcdir}/${pkgname}-${pkgver}
go build -o bin/armor cmd/armor/main.go
}
package() {
cd ${srcdir}/${pkgname}-${pkgver}
install -D -m755 bin/armor ${pkgdir}/usr/bin/armor
}
This at least works for the basic no-config test case.
Hi,
I tried to active the secure plugin and It seems to break the HTTP2 connexion.
I leaved the plugin with default settings and even with the simplest configuration it's not working.
This goes to a go panic.
Am I doing something wrong?
I have tried to add another host, which should be served as static website by Armor.
But I always get this error:
{"time":"2016-11-09T16:38:32+01:00","level":"-","prefix":"armor","file":"main.go","line":"86","message":"error parsing configuration file, type=type-error, expected=[]armor.Plugin, got=object, offset=72"}
I have tried latest Armor version, and version 0.15, i think.
When I grab configuration settings from Sample configuration from https://armor.labstack.com/guide/configuration and try to use it, i also get same error.
Hello,
will armor be able to run on a raspberry pi in the future?
All the best.
Simon
Hi there,
I couldn't find a SECURITY.md
in your repository and am not sure how to best contact you privately to disclose a security issue.
Can you add a SECURITY.md
file with an e-mail to your repository, so that our system can send you the vulnerability details? GitHub suggests that a security policy is the best way to make sure security issues are responsibly disclosed.
Once you've done that, you should receive an e-mail within the next hour with more info.
Thanks! (cc @huntr-helper)
Let's Encrypt has permanently disable the TLS-SNI challenge.
For what I see, TLS-SNI
is the only way Armor
and Echo
can get certificates.
I tried to update Echo
to use HTTP-01
but it needs to use the other HTTP handler (port 80
).
This become a heavy work and I don't have the time to find a nice way to do it.
When execute armor.exe as below, I could not set %current_workspace% as root directory
set "current_workspace=%cd%"
armor.exe --root %current_workspace% -c .\armor-set\config.yml
Although I solved this by modifying root section in config.yml using sed but, I think that supporting would be better. :)
Testing env. : MS-Windows10
Perhaps I missed something in the documentation, but is there a way to integrate PHP with Armor?
Thank you!
I wonder if I can enable auto certification apply without port 443 occupied? I only need armor to serve plain HTTP at port 80 but I need tls cert for another app that runs at port 443.
This version should be included.
acme: golang/crypto@a950601
Fix temporary:
tls:
address: ":443"
auto: true
directory_url: "https://acme-v02.api.letsencrypt.org/directory"
When installing via go get
the build fails.
$ go get github.com/labstack/armor/cmd/armor
# github.com/labstack/armor/plugin
../go/src/github.com/labstack/armor/plugin/nats.go:58: cannot use body (type func() io.Reader) as type io.Reader in argument to ioutil.ReadAll:
func() io.Reader does not implement io.Reader (missing Read method)
../go/src/github.com/labstack/armor/plugin/proxy.go:93: req.Header.Get undefined (type func() engine.Header has no field or method Get)
../go/src/github.com/labstack/armor/plugin/proxy.go:94: cannot use res (type engine.Response) as type http.ResponseWriter in argument to p.wsProxy(t).ServeHTTP:
engine.Response does not implement http.ResponseWriter (wrong type for Header method)
have Header() engine.Header
want Header() http.Header
../go/src/github.com/labstack/armor/plugin/proxy.go:94: http.Request.Body is a field, not a method
../go/src/github.com/labstack/armor/plugin/proxy.go:94: cannot use req (type engine.Request) as type *http.Request in argument to p.wsProxy(t).ServeHTTP
../go/src/github.com/labstack/armor/plugin/proxy.go:96: cannot use res (type engine.Response) as type http.ResponseWriter in argument to p.httpProxy(t).ServeHTTP:
engine.Response does not implement http.ResponseWriter (wrong type for Header method)
have Header() engine.Header
want Header() http.Header
../go/src/github.com/labstack/armor/plugin/proxy.go:96: http.Request.Body is a field, not a method
../go/src/github.com/labstack/armor/plugin/proxy.go:96: cannot use req (type engine.Request) as type *http.Request in argument to p.httpProxy(t).ServeHTTP
../go/src/github.com/labstack/armor/plugin/redirect.go:90: undefined: middleware.HTTPSNonWWWRedirectWithConfig
I've been setting up armor to proxy a couple of services on my own server. I'm running into an issue when attempting to setup own cloud. Apparently this works with the webdav protocol. This uses some non-standard HTTP verbs, for instance PROPFIND
.
I'm running own cloud using the following command:
docker run -d -p 9090:80 -v /path/to/external/storage:/var/www/html owncloud:8.1
Whenever I try to connect the own cloud client to my service, it responds with a 405 { "message": "Method Not Allowed" }
. This behaviour is reproducible using the following curl
command:
curl -X PROPFIND https://<host>/remote.php/webdav/ -v
Note that performing this request on the service directly, results in a 401 since no authentication headers are sent:
curl -X PROPFIND http://localhost:9090/remote.php/webdav/ -v
I proxy the own cloud service using the following armor config:
{
"address": ":80",
"tls": {
"address": ":443",
"cert_file": "signed.crt",
"key_file": "domain.key",
"auto": true
},
"plugins": [{
"name": "https-redirect"
}],
"hosts": {
"cloud.<host>": {
"plugins": [{
"name": "proxy",
"targets": [{"name": "cloud", "url": "http://localhost:9090"}]
}]
},
"build.<host>": {
"plugins": [{
"name": "proxy",
"targets": [{"name": "build", "url": "http://localhost:9000"}]
}]
}
}
}
Also the following log line is produced whenever I attempt to setup own cloud:
{"time":"2018-03-11T18:36:40.171463672+01:00","level":"ERROR","prefix":"armor","file":"echo.go","line":"285","message":"code=405, message=Method Not Allowed"}
fastcgi: true
# or
protocol: "fastcgi"?
I don't see any plugin that supports markdown files. Please add support for md files. Let me know if there is a way of doing this.
ref Homebrew/homebrew-core#22250
==> brew test armor --verbose
==> FAILED
Testing armor
/usr/bin/sandbox-exec -f /tmp/homebrew20171230-5697-xr5sjw.sb /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby -W0 -I /usr/local/Homebrew/Library/Homebrew -- /usr/local/Homebrew/Library/Homebrew/test.rb /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/armor.rb --verbose
___
/ _ | ______ _ ___ ____
/ __ |/ __/ ' \/ _ \/ __/
/_/ |_/_/ /_/_/_/\___/_/ v0.3.6
Uncomplicated, modern HTTP server
https://armor.labstack.com
________________________O/_______
O\
⇨ http server started on :8080
⇨ http server started on [::]:8080
==> curl -sI http://localhost:8080
{"time":"2017-12-30T07:57:23.900908Z","level":"ERROR","prefix":"armor","file":"echo.go","line":"285","message":"code=404, message=Not Found"}
{"time":"2017-12-30T07:57:23.901203Z","id":"","remote_ip":"::1","host":"localhost:8080","method":"HEAD","uri":"/","status":404, "latency":392335,"latency_human":"392.335µs","bytes_in":0,"bytes_out":0}
Error: armor: failed
</200 OK/m> expected to be =~
<"HTTP/1.1 404 Not Found\r\nServer: armor/0.3.6\r\nDate: Sat, 30 Dec 2017 07:57:23 GMT\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n">.
The test runs
test do
begin
pid = fork do
exec "#{bin}/armor"
end
sleep 1
output = shell_output("curl -sI http://localhost:8080")
assert_match /200 OK/m, output
ensure
Process.kill("HUP", pid)
end
end
The latest commit was on May 6
Is it abandoned?
I tried multiple times now to add some headers to some of my hosts and to active GZIP on specific paths.
I never made it because in fact the configuration of the plugin is very hazardous.
After many tries, it appears that plugins are loaded randomly.
I tried to check if the plugging order mater but it seams like it does not.
Here is an config example:
---
address: ":8080"
hosts:
localhost:
paths:
"/":
plugins:
-
name: static
browse: true
html5: true
root: ./
-
name: header
set:
Content-Security-Policy: "default-src 'self' data:"
Expect-CT: max-age=604800
Feature-Policy: "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"
Referrer-Policy: strict-origin-when-cross-origin
Strict-Transport-Security: "max-age=15780000; includeSubdomains"
X-Content-Type-Option: nosniff
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: "1; mode=block"
-
name: gzip
level: 3
"/API/content/":
plugins:
-
browse: true
html5: true
name: static
root: ./
-
name: header
set:
File: "true"
# plugins:
# -
# browse: true
# html5: true
# name: static
# root: ./
read_timeout: 129600
write_timeout: 129600
You can make it even simpler but here is the point.
If I run the process with the same config and same build I have random result:
curl --compressed --head localhost:8080/
HTTP/1.1 200 OK
Content-Security-Policy: default-src 'self' data:
Content-Type: text/html; charset=UTF-8
Expect-Ct: max-age=604800
Feature-Policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'
Referrer-Policy: strict-origin-when-cross-origin
Server: armor/0.4.13
Strict-Transport-Security: max-age=15780000; includeSubdomains
X-Content-Type-Option: nosniff
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
Date: Thu, 13 Jun 2019 10:03:27 GMT
Content-Length: 928
curl --compressed --head localhost:8080/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: armor/0.4.13
Date: Thu, 13 Jun 2019 10:31:35 GMT
curl --compressed --head localhost:8080/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: armor/0.4.13
Date: Thu, 13 Jun 2019 10:31:36 GMT
curl --compressed --head localhost:8080/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: armor/0.4.13
Date: Thu, 13 Jun 2019 10:31:50 GMT
curl --compressed --head localhost:8080/
HTTP/1.1 200 OK
Content-Encoding: gzip
Content-Security-Policy: default-src 'self' data:
Content-Type: text/html; charset=UTF-8
Expect-Ct: max-age=604800
Feature-Policy: accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'
Referrer-Policy: strict-origin-when-cross-origin
Server: armor/0.4.13
Strict-Transport-Security: max-age=15780000; includeSubdomains
Vary: Accept-Encoding
X-Content-Type-Option: nosniff
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
Date: Thu, 13 Jun 2019 10:31:57 GMT
Content-Length: 923
It looks like the static plugin is always loaded but the GZIP and header are not always.
In the first command header are OK but not the GZIP.
In the second, third and fourth none GZIP or header are loaded.
And in the last one finally is what I expect.
We can't relay on this behavior and I did not found where to dig.
Please take a look to this, because it's a terrible thing.
Using the body-limit
plugin, globally or at the host level:
- name: body-limit
limit: 500MB
The main function panic:
panic: echo: invalid body-limit=
goroutine 1 [running]:
github.com/labstack/armor/vendor/github.com/labstack/echo/middleware.BodyLimitWithConfig(0x82f478, 0x0, 0x0, 0x0, 0x0)
/Users/vr/Projects/labstack/armor/src/github.com/labstack/armor/vendor/github.com/labstack/echo/middleware/body_limit.go:63 +0x2bf
github.com/labstack/armor/plugin.(*BodyLimit).Init(0xc42004dc20, 0x7aa960, 0xc42000fb00)
/Users/vr/Projects/labstack/armor/src/github.com/labstack/armor/plugin/body_limit.go:16 +0x4e
github.com/labstack/armor/plugin.Decode(0xc42000fb00, 0xc420108120, 0xc42006cea0, 0x9ea220, 0xc420072960, 0x0, 0x0)
/Users/vr/Projects/labstack/armor/src/github.com/labstack/armor/plugin/plugin.go:117 +0x22c
github.com/labstack/armor/http.(*HTTP).LoadPlugins(0xc4200f2ca0)
/Users/vr/Projects/labstack/armor/src/github.com/labstack/armor/http/http.go:149 +0xe5
main.main()
/Users/vr/Projects/labstack/armor/src/github.com/labstack/armor/cmd/armor/main.go:100 +0x326
And the static plugin is not working either.
The server respond me with 404
.
A working configuration on 0.3.5 but not on 0.3.6 (docker image):
address: ":80"
tls:
address: ":443"
auto: true
cache_dir: /etc/armor/certs
plugins:
- name: https-redirect
- name: body-limit
limit: 500MB
# - name: secure
hosts:
dom.com:
paths:
"/":
plugins:
- name: static
root: /var/www/test
@irundaia I made a fix, do you want to try with the following files?
Originally posted by @vishr in #40 (comment)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.