housekeeping: code cleanup, tests and hello travis

This commit is contained in:
Jan Halfar 2016-02-17 13:30:07 +01:00
parent a7f428b26d
commit 9164c6064e
29 changed files with 426 additions and 475 deletions

View File

@ -1,3 +1,5 @@
[![Travis CI](https://travis-ci.org/foomo/gofoomo.svg?branch=master)](https://travis-ci.org/foomo/gofoomo)
# gofoomo
Gofoomo lets you use Go in your foomo project. It also lets you use php in your Go project.
@ -28,7 +30,32 @@ Gofoomo lets you intercept and implement calls to foomo json rpc services. In ad
## Access foomo configurations
Gofoomo gives you access to foomo configurations from Go. Hint: if your php configuration objects are well annotated they are essentially value objects and corresponding structs can easily be generated with Foomo.Go.
Gofoomo gives you access to foomo configurations from Go. Hint: if your php configuration objects are well annotated they are essentially value objects and corresponding structs can easily be generated with Foomo.Go.
## foomo-bert
Is a command line utility, that helps you with the setup of foomo installations.
```bash
go install github.com/foomo/gofoomo/foomo-bert
foomo-bert -help
usage: foomo-bert <command>
foomo-bert prepare :
-dir string
path/to/your/foomo/root
-run-mode string
foomo run mode test | development | production
foomo-bert reset :
-addr string
address of the foomo server
-dir string
path/to/your/foomo/root
-main-module string
name of main module (default "Foomo")
-run-mode string
foomo run mode test | development | production
```
## More to come, but not much more

View File

@ -13,7 +13,7 @@ var flagConfig = flag.String("config", "", "config file")
func main() {
fmt.Println("I am a little demo program")
flag.Parse()
proxyServer, err := proxy.NewProxyServerWithConfig(*flagConfig)
proxyServer, err := proxy.NewServerWithConfig(*flagConfig)
if err != nil {
log.Fatal(err.Error())
}

View File

@ -8,7 +8,6 @@ import (
"os"
"path"
"github.com/bgentry/speakeasy"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/foomo/bert"
"github.com/foomo/gofoomo/utils"
@ -144,14 +143,12 @@ func main() {
os.Exit(1)
}
if len(*flagsPrepare.admin) > 0 {
fmt.Println("adding admin user", *flagsPrepare.admin)
passwd, err := speakeasy.Ask("enter password for " + *flagsPrepare.admin)
err = b.PrepareAdmin(*flagsPrepare.admin)
if err != nil {
fmt.Println("could not read password, giving up")
fmt.Println("could not set password for " + *flagsPrepare.admin + " " + err.Error())
os.Exit(1)
}
fmt.Println("adding password", passwd, "for", *flagsPrepare.admin)
os.Exit(0)
}
case "reset":
fs, flagsReset := foomoFlagsetReset()

View File

@ -1,17 +0,0 @@
package bert
import (
"io/ioutil"
"gopkg.in/yaml.v2"
)
func readConfig(filename string) (config map[string][]string, err error) {
config = make(map[string][]string)
yamlBytes, err := ioutil.ReadFile(filename)
if err != nil {
return
}
err = yaml.Unmarshal(yamlBytes, config)
return
}

View File

@ -1,34 +0,0 @@
package bert
import (
"path"
"testing"
"github.com/foomo/gofoomo/utils"
)
func TestReadConfig(t *testing.T) {
config, err := readConfig(path.Join(utils.GetCurrentDir(), "basicauth_test", "test.yml"))
utils.PanicOnErr(err)
expectedAuthDomains := map[string][]string{
"default": []string{
"secret/foo",
"secret/bar",
},
"sepp": []string{
"secret/sepp/test",
},
}
for expectedAuthDomain, secrets := range expectedAuthDomains {
configSecrets, ok := config[expectedAuthDomain]
if !ok {
t.Fatal("missing auth domain", expectedAuthDomain)
}
for index, secret := range secrets {
configSecret := configSecrets[index]
if configSecret != secret {
t.Fatal("unexpected secret", secret, "should be", configSecret)
}
}
}
}

View File

@ -1,3 +0,0 @@
jan:$2y$05$xHK1qpXKtLof8.5WYEQGVuR0GFuTdzcbjNHfUMhK6PjoU4TtD6DmW
test:$2y$05$aUToamwisvuLuRtFcpEvY./yT83dGwlMMa8bKD5IduagQwYIv4gym
foo:$2y$05$25AK9DVp0P4hpqRq5Zu4HeA0iWoaR/exloH07mKCrdZ4pMD0q8H6.

View File

@ -1,6 +0,0 @@
---
default:
- secret/foo
- secret/bar
sepp:
- secret/sepp/test

View File

@ -1,20 +1,19 @@
package bert
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"path"
"github.com/foomo/gofoomo/foomo"
)
// Bert is a foomo helper
type Bert struct {
foomo *foomo.Foomo
}
// NewBert constructor
func NewBert(f *foomo.Foomo) *Bert {
return &Bert{
foomo: f,
@ -27,29 +26,7 @@ type moduleList struct {
const line = "-------------------------------------------------------------------------------"
func (b *Bert) Reset(mainModuleName string) error {
err := b.get("resetting everything", "/foomo/hiccup.php?class=hiccup&action=resetEverything")
if err != nil {
return errors.New("failed to reset everything: " + err.Error())
}
err = b.get("enabling main module "+mainModuleName, "/foomo/core.php/enableModule/"+mainModuleName)
if err != nil {
return errors.New("enabling main module failed" + err.Error())
}
err = b.get("trying to create missing module resources", "/foomo/core.php/tryCreateModuleResources")
if err != nil {
return errors.New("failed to create module resources" + err.Error())
}
err = b.get("running make clean all", "/foomo/core.php/make/clean,all")
if err != nil {
return errors.New("make clean, all failed: " + err.Error())
}
return nil
}
// plain http get
func (b *Bert) get(explanation string, path string) error {
fmt.Println(explanation)
fmt.Println(line)
@ -73,31 +50,3 @@ func (b *Bert) get(explanation string, path string) error {
fmt.Println(line)
return nil
}
func (b *Bert) Prepare() error {
b.foomo.GetVarDir()
dirs := []string{
"composer",
"docker",
path.Join("config", b.foomo.RunMode, "foomo"),
path.Join("var", b.foomo.RunMode),
path.Join("var", b.foomo.RunMode, "logs"),
path.Join("var", b.foomo.RunMode, "basicAuth"),
path.Join("var", b.foomo.RunMode, "sessions"),
path.Join("var", b.foomo.RunMode, "tmp"),
path.Join("var", b.foomo.RunMode, "logs"),
path.Join("var", b.foomo.RunMode, "cache"),
path.Join("var", b.foomo.RunMode, "modules"),
path.Join("var", b.foomo.RunMode, "htdocs", "modules"),
path.Join("var", b.foomo.RunMode, "htdocs", "modulesVar"),
}
for _, dir := range dirs {
dirToMake := path.Join(b.foomo.Root, dir)
mkdirErr := os.MkdirAll(dirToMake, 0744)
if mkdirErr != nil {
return mkdirErr
}
fmt.Println("created path", dirToMake)
}
return nil
}

63
foomo/bert/prepare.go Normal file
View File

@ -0,0 +1,63 @@
package bert
import (
"errors"
"fmt"
"os"
"path"
"github.com/bgentry/speakeasy"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/htpasswd"
)
// Prepare an installation (very basic skeleton)
func (b *Bert) Prepare() error {
b.foomo.GetVarDir()
dirs := []string{
"composer",
"docker",
path.Join("config", b.foomo.RunMode, "foomo"),
path.Join("var", b.foomo.RunMode),
path.Join("var", b.foomo.RunMode, "logs"),
path.Join("var", b.foomo.RunMode, "basicAuth"),
path.Join("var", b.foomo.RunMode, "sessions"),
path.Join("var", b.foomo.RunMode, "tmp"),
path.Join("var", b.foomo.RunMode, "logs"),
path.Join("var", b.foomo.RunMode, "cache"),
path.Join("var", b.foomo.RunMode, "modules"),
path.Join("var", b.foomo.RunMode, "htdocs", "modules"),
path.Join("var", b.foomo.RunMode, "htdocs", "modulesVar"),
}
for _, dir := range dirs {
dirToMake := path.Join(b.foomo.Root, dir)
mkdirErr := os.MkdirAll(dirToMake, 0744)
if mkdirErr != nil {
return mkdirErr
}
fmt.Println("created path", dirToMake)
}
return nil
}
// PrepareAdmin asks and adds basic auth credentials for foomo default auth\
// domain
func (b *Bert) PrepareAdmin(admin string) error {
fmt.Println("adding admin user", admin)
passwd, err := speakeasy.Ask("enter password for " + admin + " 🔑 :\n")
if err != nil {
return errors.New("could not read password, giving up")
}
passwordFile := b.foomo.GetBasicAuthFilename(foomo.DefaultBasicAuthDomainName)
fmt.Println("adding password for admin in:", passwordFile)
err = htpasswd.SetPassword(passwordFile, admin, passwd, htpasswd.HashBCrypt)
if err != nil {
return errors.New("could not write default basic auth password for admin: " + err.Error())
}
fmt.Println("added password")
fmt.Println("DONE")
return nil
}

27
foomo/bert/reset.go Normal file
View File

@ -0,0 +1,27 @@
package bert
import "errors"
// Reset reset a bert installation
func (b *Bert) Reset(mainModuleName string) error {
err := b.get("resetting everything", "/foomo/hiccup.php?class=hiccup&action=resetEverything")
if err != nil {
return errors.New("failed to reset everything: " + err.Error())
}
err = b.get("enabling main module "+mainModuleName, "/foomo/core.php/enableModule/"+mainModuleName)
if err != nil {
return errors.New("enabling main module failed" + err.Error())
}
err = b.get("trying to create missing module resources", "/foomo/core.php/tryCreateModuleResources")
if err != nil {
return errors.New("failed to create module resources" + err.Error())
}
err = b.get("running make clean all", "/foomo/core.php/make/clean,all")
if err != nil {
return errors.New("make clean, all failed: " + err.Error())
}
return nil
}

View File

@ -11,12 +11,12 @@ import (
)
func get(foomo *foomo.Foomo, path ...string) (data []byte, err error) {
callUrl := foomo.GetURLWithCredentialsForDefaultBasicAuthDomain()
callURL := foomo.GetURLWithCredentialsForDefaultBasicAuthDomain()
encodedPath := ""
for _, pathEntry := range path {
encodedPath += "/" + url.QueryEscape(pathEntry)
}
req, err := http.NewRequest("GET", callUrl+"/foomo/core.php"+encodedPath, nil)
req, err := http.NewRequest("GET", callURL+"/foomo/core.php"+encodedPath, nil)
if err != nil {
return
}
@ -36,19 +36,19 @@ func get(foomo *foomo.Foomo, path ...string) (data []byte, err error) {
return data, err
}
// GetJSON call into foomo and unmarshal response using encoding/json
func GetJSON(foomo *foomo.Foomo, target interface{}, path ...string) error {
data, err := get(foomo, path...)
if err == nil {
return json.Unmarshal(data, &target)
} else {
return err
}
return err
}
// GetConfig retrieve a domain config
func GetConfig(foomo *foomo.Foomo, target interface{}, moduleName string, configName string, domain string) (err error) {
if len(domain) == 0 {
return GetJSON(foomo, target, "config", moduleName, configName)
} else {
return GetJSON(foomo, target, "config", moduleName, configName, domain)
}
return GetJSON(foomo, target, "config", moduleName, configName, domain)
}

View File

@ -2,8 +2,15 @@ package core
import (
"encoding/json"
"github.com/foomo/gofoomo/foomo"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/foomo/bert"
)
type CoreConfig struct {
@ -15,9 +22,41 @@ type CoreConfig struct {
var testFoomo *foomo.Foomo
func poe(err error, msg string) {
if err != nil {
panic(msg + " : " + err.Error())
}
}
func getTestServer() *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`{
"enabledModules": [
"Foomo"
],
"availableModules": [
"Foomo"
]
}`))
}))
return ts
}
func getTestFoomo() *foomo.Foomo {
if testFoomo == nil {
f, _ := foomo.NewFoomo("/Users/jan/vagrant/schild/www/schild", "test", "http://schild-local-test.bestbytes.net")
ts := getTestServer()
tmp := os.TempDir()
dir, err := ioutil.TempDir(tmp, "dummy-foomo")
poe(err, "failed to get temp dir")
bareFoomo, err := foomo.BareFoomo(dir, "test")
poe(err, "failed to get bare foomo")
b := bert.NewBert(bareFoomo)
b.Prepare()
f, err := foomo.NewFoomo(dir, "test", fmt.Sprint(ts.URL))
if err != nil {
panic("invalid test foomo " + err.Error())
}
testFoomo = f
}
return testFoomo

View File

@ -1,25 +1,25 @@
package foomo
import (
"crypto/sha1"
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"net/http"
u "net/url"
"os"
"strings"
"github.com/foomo/htpasswd"
)
const (
RunModeTest = "test"
// RunModeTest run mode test
RunModeTest = "test"
// RunModeDevelopment run mode development
RunModeDevelopment = "development"
RunModeProduction = "production"
// RunModeProduction run mode production
RunModeProduction = "production"
// DefaultBasicAuthDomainName name of default basic auth domain
DefaultBasicAuthDomainName = "default"
)
const shaPrefix = "{SHA}"
// Foomo foomo go wrapper
type Foomo struct {
Root string
@ -72,118 +72,56 @@ func makeFoomo(foomoDir string, runMode string, address string, init bool) (f *F
if init {
authErr := f.setupBasicAuthCredentials()
if authErr != nil {
return nil, authErr
return nil, errors.New("can not set up auth: " + authErr.Error())
}
}
return f, err
}
func (f *Foomo) BasicAuth(domain string, user string, password string) bool {
for _, line := range strings.Split(f.getBasicAuthFileContentsForDomain(domain), "\n") {
lineParts := strings.Split(line, ":")
if len(lineParts) == 2 && lineParts[0] == user {
hash := getBasicAuthHash(password)
return hash == lineParts[1]
}
}
return false
}
func (f *Foomo) BasicAuthForRequest(w http.ResponseWriter, incomingRequest *http.Request, domain string, realm string, denialHTML string) bool {
forbidden := func() bool {
realm := strings.Replace(realm, "\"", "'", -1)
w.Header().Set("Www-Authenticate", "Basic realm=\""+realm+"\"")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(denialHTML))
return false
}
authHeader := incomingRequest.Header.Get("Authorization")
if len(authHeader) == 0 {
return forbidden()
}
auth, base64DecodingErr := base64.StdEncoding.DecodeString(strings.TrimPrefix(authHeader, "Basic "))
if base64DecodingErr != nil {
return forbidden()
}
authParts := strings.Split(string(auth), ":")
if len(authParts) != 2 {
return forbidden()
}
if f.BasicAuth(domain, authParts[0], authParts[1]) {
return true
} else {
return forbidden()
}
}
func (f *Foomo) getBasicAuthFileContentsForDomain(domain string) string {
basicAuthFilename := f.GetBasicAuthFilename(domain)
bytes, err := ioutil.ReadFile(basicAuthFilename)
if err != nil {
return ""
} else {
return string(bytes)
}
}
func (f *Foomo) setupBasicAuthCredentials() error {
f.basicAuthCredentials.user = "gofoomo"
f.basicAuthCredentials.password = makeToken(50)
return ioutil.WriteFile(f.GetBasicAuthFilename("default"), []byte(setBasicAuthForUserInBasicAuthFileContents(f.getBasicAuthFileContentsForDomain("default"), f.basicAuthCredentials.user, f.basicAuthCredentials.password)), 0644)
}
func setBasicAuthForUserInBasicAuthFileContents(basicAuthFileContents string, user string, password string) string {
newLines := make([]string, 0)
LineLoop:
for _, line := range strings.Split(basicAuthFileContents, "\n") {
lineParts := strings.Split(line, ":")
if len(lineParts) == 2 && lineParts[0] == user {
continue LineLoop
} else if len(line) > 0 {
newLines = append(newLines, line)
}
}
newLines = append(newLines, user+":"+getBasicAuthHash(password))
return strings.Join(newLines, "\n") + "\n"
}
func getBasicAuthHash(password string) string {
s := sha1.New()
s.Write([]byte(password))
passwordSum := []byte(s.Sum(nil))
return shaPrefix + base64.StdEncoding.EncodeToString(passwordSum)
return htpasswd.SetPassword(f.GetBasicAuthFilename("default"), f.basicAuthCredentials.user, f.basicAuthCredentials.password, htpasswd.HashBCrypt)
}
// GetURLWithCredentialsForDefaultBasicAuthDomain i.e. sth. like http(s)://user:password@foomo-server.org(:8080)
func (f *Foomo) GetURLWithCredentialsForDefaultBasicAuthDomain() string {
url, _ := u.Parse(f.URL.String())
url.User = u.UserPassword(f.basicAuthCredentials.user, f.basicAuthCredentials.password)
return url.String()
}
// GetBasicAuthCredentialsForDefaultBasicAuthDomain user, password generated for the local foomo instance
func (f *Foomo) GetBasicAuthCredentialsForDefaultBasicAuthDomain() (user string, password string) {
return f.basicAuthCredentials.user, f.basicAuthCredentials.password
}
// GetModuleDir root dir of a module
func (f *Foomo) GetModuleDir(moduleName string, dir string) string {
return f.Root + "/modules/" + moduleName + "/" + dir
}
// GetVarDir root var dir for the current run mode
func (f *Foomo) GetVarDir() string {
return f.Root + "/var/" + f.RunMode
}
// GetModuleHtdocsDir htdocs dir in a module
func (f *Foomo) GetModuleHtdocsDir(moduleName string) string {
return f.GetModuleDir(moduleName, "htdocs")
}
// GetModuleCacheDir cache dir for a module
func (f *Foomo) GetModuleCacheDir(moduleName string) string {
return f.GetVarDir() + "/cache/" + moduleName
}
// GetModuleHtdocsVarDir module htdocs var dir
func (f *Foomo) GetModuleHtdocsVarDir(moduleName string) string {
return f.GetVarDir() + "/htdocs/modulesVar/" + moduleName
}
// GetBasicAuthFilename basic auth file name for a domain
func (f *Foomo) GetBasicAuthFilename(domain string) string {
return f.GetVarDir() + "/basicAuth/" + domain
}

View File

@ -1,23 +1,22 @@
package foomo
import (
"strings"
"os"
"testing"
)
func TestSetBasicAuthForUserInBasicAuthFileContents(t *testing.T) {
ba := "foo:bar\ntest:gone\nhansi:toll"
newBa := setBasicAuthForUserInBasicAuthFileContents(ba, "test", "test")
if len(strings.Split(newBa, "\n")) != 3 {
t.Fatal("wrong line count")
}
}
func getTestFoomoForFSStuff() *Foomo {
f, _ := makeFoomo("/var/www/foomo", "test", "http://test.foomo", false)
tempDir := os.TempDir()
f, err := BareFoomo(tempDir[0:len(tempDir)-1], "test")
if err != nil {
panic(err)
}
return f
}
func assertTempPath(t *testing.T, topic string, expected string, actual string) {
assertStringsEqual(t, topic, os.TempDir()+expected, actual)
}
func assertStringsEqual(t *testing.T, topic string, expected string, actual string) {
if actual != expected {
t.Fatal(topic, "actual: ", actual, " != expected: ", expected)
@ -26,22 +25,42 @@ func assertStringsEqual(t *testing.T, topic string, expected string, actual stri
func TestGetVarDir(t *testing.T) {
actual := getTestFoomoForFSStuff().GetVarDir()
expected := "/var/www/foomo/var/test"
assertStringsEqual(t, "var dir", expected, actual)
expected := "var/test"
assertTempPath(t, "var dir", expected, actual)
}
func TestGetModuleDir(t *testing.T) {
assertStringsEqual(t, "module dir", "/var/www/foomo/modules/Foomo/htdocs", getTestFoomoForFSStuff().GetModuleDir("Foomo", "htdocs"))
assertTempPath(
t,
"module dir",
"modules/Foomo/htdocs",
getTestFoomoForFSStuff().GetModuleDir("Foomo", "htdocs"),
)
}
func TestGetModuleHtdocsDir(t *testing.T) {
assertStringsEqual(t, "module htdocs dir", "/var/www/foomo/modules/Foomo/htdocs", getTestFoomoForFSStuff().GetModuleHtdocsDir("Foomo"))
assertTempPath(
t,
"module htdocs dir",
"modules/Foomo/htdocs",
getTestFoomoForFSStuff().GetModuleHtdocsDir("Foomo"),
)
}
func TestGetModuleHtdocsVarDir(t *testing.T) {
assertStringsEqual(t, "module htdocs var dir", "/var/www/foomo/var/test/htdocs/modulesVar/Foomo", getTestFoomoForFSStuff().GetModuleHtdocsVarDir("Foomo"))
assertTempPath(
t,
"module htdocs var dir",
"var/test/htdocs/modulesVar/Foomo",
getTestFoomoForFSStuff().GetModuleHtdocsVarDir("Foomo"),
)
}
func TestGetBasicAuthFilename(t *testing.T) {
assertStringsEqual(t, "basic auth file", "/var/www/foomo/var/test/basicAuth/sepp", getTestFoomoForFSStuff().GetBasicAuthFilename("sepp"))
assertTempPath(
t,
"basic auth file",
"var/test/basicAuth/sepp",
getTestFoomoForFSStuff().GetBasicAuthFilename("sepp"),
)
}

View File

@ -5,32 +5,26 @@ import (
"fmt"
"io/ioutil"
"github.com/foomo/tlsconfig"
"gopkg.in/yaml.v2"
)
// Auth basic auth
type Auth struct {
Domain string
Realm string
}
// TLS proxy tls config vo
type TLS struct {
Mode string
Mode tlsconfig.TLSModeServer
Address string
CertFile string
KeyFile string
}
const (
// this is serious and we do not mind loosing clients (= Mozilla "modern" compatibility)
// Compatible clients have versions equal or greater than Firefox 27, Chrome 22, IE 11, Opera 14, Safari 7, Android 4.4, Java 8
TLSModeStrict = "strict"
// ecommerce compromise
// Compatible clients (>=): Firefox 1, Chrome 1, IE 7, Opera 5, Safari 1, Windows XP IE8, Android 2.3, Java 7
TLSModeLoose = "loose"
// standard crypto/tls.Config un touched - highly compatible, but possibly insecure
TLSModeDefault = "default"
)
// Config proxy configuration
type Config struct {
// how should the proxy server run
Server struct {
@ -51,6 +45,7 @@ type Config struct {
AppOptions map[string]string
}
// ReadConfig from a file
func ReadConfig(filename string) (config *Config, err error) {
config = &Config{}
yamlBytes, err := ioutil.ReadFile(filename)
@ -62,12 +57,12 @@ func ReadConfig(filename string) (config *Config, err error) {
return nil, err
}
if config.Server.TLS.Mode == "" {
config.Server.TLS.Mode = TLSModeDefault
config.Server.TLS.Mode = tlsconfig.TLSModeServerDefault
}
switch config.Server.TLS.Mode {
case TLSModeDefault, TLSModeLoose, TLSModeStrict:
case tlsconfig.TLSModeServerDefault, tlsconfig.TLSModeServerLoose, tlsconfig.TLSModeServerStrict:
default:
return nil, errors.New("unknown server.tls.mode: " + config.Server.TLS.Mode + " - must be one of: " + fmt.Sprintln([]string{TLSModeDefault, TLSModeLoose, TLSModeStrict}))
return nil, errors.New("unknown server.tls.mode: " + string(config.Server.TLS.Mode) + " - must be one of: " + fmt.Sprintln([]tlsconfig.TLSModeServer{tlsconfig.TLSModeServerDefault, tlsconfig.TLSModeServerLoose, tlsconfig.TLSModeServerStrict}))
}
return config, nil
}

View File

@ -1,38 +1,53 @@
package handler
import (
"net/http"
"github.com/abbot/go-http-auth"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/proxy"
"log"
"net/http"
)
// AuthWrapper wraps proxy handlers with a basic authentication
type AuthWrapper struct {
handler proxy.Handler
foomo *foomo.Foomo
authDomain string
handler proxy.Handler
foomo *foomo.Foomo
// authDomain string
denialHTML string
realm string
//realm string
authenticator *auth.BasicAuth
}
// NewAuthWrapper wrap a proxy handler with basic auth
func NewAuthWrapper(f *foomo.Foomo, h proxy.Handler, authDomain string, realm string, denialHTML string) *AuthWrapper {
secretProvider := auth.HtpasswdFileProvider(f.GetBasicAuthFilename(authDomain))
return &AuthWrapper{
handler: h,
foomo: f,
realm: realm,
authDomain: authDomain,
denialHTML: denialHTML,
handler: h,
foomo: f,
// realm: realm,
// authDomain: authDomain,
denialHTML: denialHTML,
authenticator: auth.NewBasicAuthenticator(realm, secretProvider),
}
}
// HandlesRequest am I responsible to handle that request
func (a *AuthWrapper) HandlesRequest(incomingRequest *http.Request) bool {
// asking my underlying handler
return a.handler.HandlesRequest(incomingRequest)
}
func (a *AuthWrapper) ServeHTTP(w http.ResponseWriter, incomingRequest *http.Request) {
if !a.foomo.BasicAuthForRequest(w, incomingRequest, a.authDomain, "authenticate", "nope") {
log.Println("auth wrapper access denied for", incomingRequest.RequestURI)
func (a *AuthWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
user := a.authenticator.CheckAuth(r)
if len(user) == 0 {
a.authenticator.RequireAuth(w, r)
}
user = a.authenticator.CheckAuth(r)
if len(user) == 0 {
w.Write([]byte(a.denialHTML))
return
}
a.handler.ServeHTTP(w, incomingRequest)
a.handler.ServeHTTP(w, r)
}

View File

@ -2,14 +2,16 @@ package images
import (
"errors"
"github.com/foomo/gofoomo/foomo"
"log"
"net/http"
"os"
"strings"
"time"
"github.com/foomo/gofoomo/foomo"
)
// ImageInfo image cache meta data
type ImageInfo struct {
Filename string
Etag string
@ -18,6 +20,7 @@ type ImageInfo struct {
Expires int64
}
// NewImageInfo constructor
func NewImageInfo(response *http.Response) *ImageInfo {
i := new(ImageInfo)
if response != nil {
@ -35,11 +38,13 @@ func (i *ImageInfo) getHeader(name string) []string {
return h
}
// ImageRequestResult result vo
type ImageRequestResult struct {
Error error
Request *ImageRequest
}
// ImageRequest request vo
type ImageRequest struct {
Id string
IncomingRequest *http.Request
@ -48,6 +53,7 @@ type ImageRequest struct {
ImageInfo *ImageInfo
}
// NewImageRequest image request constructor
func NewImageRequest(id string, incomingRequest *http.Request, foomoMediaClientInfoCookie *http.Cookie) *ImageRequest {
r := new(ImageRequest)
r.Id = id
@ -64,6 +70,7 @@ func (i *ImageRequest) execute(cache *Cache) error {
return result.Error
}
// Cache image cache
type Cache struct {
Directory map[string]*ImageInfo
Foomo *foomo.Foomo
@ -75,6 +82,7 @@ type Cache struct {
//doneChannel chan *ImageRequest
}
// NewCache cache constructor
func NewCache(f *foomo.Foomo) *Cache {
c := new(Cache)
c.Foomo = f
@ -124,6 +132,7 @@ func (c *Cache) runLoop() {
}
// Get get image with the given breakpoints
func (c *Cache) Get(request *http.Request, breakPoints []int64) (info *ImageInfo, err error) {
cookie := getFoomoMediaClientInfoCookie(request.Cookies(), breakPoints)
@ -174,49 +183,47 @@ func (c *Cache) getImage(incomingRequest *http.Request, foomoMediaClientInfoCook
if err != nil {
return NewImageInfo(nil), err
} else {
request.AddCookie(foomoMediaClientInfoCookie)
if c.foomoSessionCookie != nil {
request.AddCookie(c.foomoSessionCookie)
}
request.AddCookie(foomoMediaClientInfoCookie)
if c.foomoSessionCookie != nil {
request.AddCookie(c.foomoSessionCookie)
}
request.URL.Opaque = incomingRequest.URL.Opaque
request.URL.Host = c.Foomo.URL.Host
request.URL.Scheme = c.Foomo.URL.Scheme
imageServerResponse, err := c.client.Do(request)
i = NewImageInfo(imageServerResponse)
if imageServerResponse != nil {
defer imageServerResponse.Body.Close()
}
if err != nil {
if imageServerResponse != nil && imageServerResponse.StatusCode == http.StatusMovedPermanently {
return nil, errors.New("unexpected redirect")
}
request.URL.Opaque = incomingRequest.URL.Opaque
request.URL.Host = c.Foomo.URL.Host
request.URL.Scheme = c.Foomo.URL.Scheme
imageServerResponse, err := c.client.Do(request)
i := NewImageInfo(imageServerResponse)
if imageServerResponse != nil {
defer imageServerResponse.Body.Close()
return nil, errors.New("unexpected error " + err.Error())
}
i.StatusCode = imageServerResponse.StatusCode
c.checkFoomoSessionCookie(imageServerResponse)
switch i.StatusCode {
case http.StatusOK, http.StatusNotFound:
t, timeErr := time.Parse(time.RFC1123, imageServerResponse.Header.Get("Expires"))
if timeErr == nil {
i.Expires = t.Unix()
} else {
i.Expires = 0
i.Expires = time.Now().Unix() + 3600
log.Println("could not parse expiration time", timeErr)
}
if err != nil {
if imageServerResponse != nil && imageServerResponse.StatusCode == http.StatusMovedPermanently {
return nil, errors.New("unexpected redirect")
} else {
return nil, errors.New("unexpected error " + err.Error())
}
panic(errors.New("unexpected error " + err.Error()))
} else {
i.StatusCode = imageServerResponse.StatusCode
c.checkFoomoSessionCookie(imageServerResponse)
switch i.StatusCode {
case http.StatusOK, http.StatusNotFound:
t, timeErr := time.Parse(time.RFC1123, imageServerResponse.Header.Get("Expires"))
if timeErr == nil {
i.Expires = t.Unix()
} else {
i.Expires = 0
i.Expires = time.Now().Unix() + 3600
log.Println("could not parse expiration time", timeErr)
}
if err != nil {
panic(errors.New("unexpected error " + err.Error()))
} else {
i.Etag = imageServerResponse.Header.Get("Etag")
}
default:
return nil, errors.New("unexpected reply with status " + imageServerResponse.Status)
}
i.Etag = imageServerResponse.Header.Get("Etag")
}
return i, nil
default:
return nil, errors.New("unexpected reply with status " + imageServerResponse.Status)
}
return i, nil
}

View File

@ -1,16 +1,19 @@
package images
import (
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/foomo/core"
"sort"
"strconv"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/foomo/core"
)
// MediaServerConfig foomo config helper
type MediaServerConfig struct {
Grid map[string]map[string]int64 `json:"grid"`
}
// SessionConfig foomo config helper
type SessionConfig struct {
Name string `json:"name"`
}
@ -24,7 +27,7 @@ func getBreakPoints(f *foomo.Foomo) []int64 {
}
breakPointsInt := []int{}
for breakPointString, _ := range c.Grid {
for breakPointString := range c.Grid {
breakPointInt, _ := strconv.Atoi(breakPointString)
if breakPointInt > 0 {
breakPointsInt = append(breakPointsInt, breakPointInt)

View File

@ -10,18 +10,24 @@ import (
)
const (
DefaultScreenWidth = 1024
DefaultScreenHeight = 768
DefaultPixelRatio = 1.0
// DefaultScreenWidth still 1024
DefaultScreenWidth = 1024
// DefaultScreenHeight like in the good old days
DefaultScreenHeight = 768
// DefaultPixelRatio in case of doubt lightweight
DefaultPixelRatio = 1.0
// FoomoMediaClientInfoCookieName that is the name of the cookie we inspect to extract the client informattions from
FoomoMediaClientInfoCookieName = "foomoMediaClientInfo"
)
// ClientInfo vo
type ClientInfo struct {
screenWidth int64
screenHeight int64
pixelRatio float64
}
// NewClientInfo constructor
func NewClientInfo() *ClientInfo {
info := new(ClientInfo)
info.screenWidth = DefaultScreenWidth
@ -36,18 +42,17 @@ func readFoomoMediaClientInfo(cookie string) (clientInfo *ClientInfo, err error)
if len(parts) != 2 {
err = errors.New(fmt.Sprint("could not separate screen size from pixel ratio", parts))
return clientInfo, err
} else {
screenSizeParts := strings.Split(parts[0], "x")
if len(screenSizeParts) != 2 {
err = errors.New(fmt.Sprint("could not find screen size components ", len(screenSizeParts), " in ", parts[0]))
} else {
clientInfo = NewClientInfo()
clientInfo.pixelRatio, _ = strconv.ParseFloat(parts[1], 32)
clientInfo.screenWidth, _ = strconv.ParseInt(screenSizeParts[0], 0, 32)
clientInfo.screenHeight, _ = strconv.ParseInt(screenSizeParts[1], 0, 32)
}
return clientInfo, err
}
screenSizeParts := strings.Split(parts[0], "x")
if len(screenSizeParts) != 2 {
err = errors.New(fmt.Sprint("could not find screen size components ", len(screenSizeParts), " in ", parts[0]))
} else {
clientInfo = NewClientInfo()
clientInfo.pixelRatio, _ = strconv.ParseFloat(parts[1], 32)
clientInfo.screenWidth, _ = strconv.ParseInt(screenSizeParts[0], 0, 32)
clientInfo.screenHeight, _ = strconv.ParseInt(screenSizeParts[1], 0, 32)
}
return clientInfo, err
}
func clampScreenWidthToGrid(screenWidth int64, breakPoints []int64) int64 {

View File

@ -2,21 +2,23 @@ package images
import (
"errors"
"github.com/foomo/gofoomo/foomo"
//"io"
//"log"
"net/http"
"os"
"strings"
"time"
"github.com/foomo/gofoomo/foomo"
)
// Adaptive adaptive images
type Adaptive struct {
Paths []string
BreakPoints []int64
Cache *Cache
}
// NewAdaptive constructor
func NewAdaptive(paths []string, f *foomo.Foomo) *Adaptive {
a := new(Adaptive)
a.Paths = paths
@ -25,6 +27,7 @@ func NewAdaptive(paths []string, f *foomo.Foomo) *Adaptive {
return a
}
// HandlesRequest request handler interface implementation
func (a *Adaptive) HandlesRequest(incomingRequest *http.Request) bool {
for _, p := range a.Paths {
if strings.HasPrefix(incomingRequest.URL.Path, p) {
@ -35,57 +38,27 @@ func (a *Adaptive) HandlesRequest(incomingRequest *http.Request) bool {
}
func (a *Adaptive) ServeHTTP(w http.ResponseWriter, incomingRequest *http.Request) {
info, err := a.Cache.Get(incomingRequest, a.BreakPoints)
//log.Println("info for request" + incomingRequest.RequestURI)
//log.Println(info)
//log.Println("------------------------------------")
if err != nil {
panic(err)
}
if info == nil {
panic(errors.New("could not get image"))
} else {
// 304 handling
file, err := os.Open(info.Filename)
if err != nil {
panic(err)
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
w.Header().Set("Expires", time.Now().Add(time.Hour * 24 * 7).Format(http.TimeFormat))
//this part handles etags in parallel with expires
/* browserEtag := incomingRequest.Header.Get("If-None-Match")
if browserEtag == info.Etag {
w.WriteHeader(http.StatusNotModified)
writeHeaders(w, info)
} else {
writeHeaders(w, info)
file, err := os.Open(info.Filename)
if err != nil {
// dummy image ?!
panic(errors.New("could not open image file " + info.Filename + " " + err.Error()))
} else {
io.Copy(w, file)
defer file.Close()
}
}
//end of ETag handling
*/
http.ServeContent(w, incomingRequest, file.Name(), fileInfo.ModTime(), file)
}
// 304 handling
file, err := os.Open(info.Filename)
if err != nil {
panic(err)
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
panic(err)
}
w.Header().Set("Expires", time.Now().Add(time.Hour*24*7).Format(http.TimeFormat))
http.ServeContent(w, incomingRequest, file.Name(), fileInfo.ModTime(), file)
}
func writeHeaders(w http.ResponseWriter, info *ImageInfo) {
@ -93,15 +66,8 @@ func writeHeaders(w http.ResponseWriter, info *ImageInfo) {
if key == "Set-Cookie" {
continue
}
/*if key == "Expires" {
//force browser cache for 1 year
w.Header().Add(key, time.Now().Add(time.Hour*24*365).Format(http.TimeFormat))
}*/
for _, value := range values {
w.Header().Add(key, value)
}
}
}

View File

@ -6,7 +6,7 @@ import (
func TestReadFoomoMediaClientInfo(t *testing.T) {
// 2560x1440@0.8999999761581421
info, err := ReadFoomoMediaClientInfo("2560x1440@0.8999999761581421")
info, err := readFoomoMediaClientInfo("2560x1440@0.8999999761581421")
if err != nil {
t.Log("parse error", err)
t.Fail()
@ -28,11 +28,11 @@ func TestClampScreenWidthToGrid(t *testing.T) {
t.Error("expected", expected, "actual", actual)
}
}
assertSize(t, 320, ClampScreenWidthToGrid(298, breakPoints))
assertSize(t, 768, ClampScreenWidthToGrid(321, breakPoints))
assertSize(t, 768, ClampScreenWidthToGrid(766, breakPoints))
assertSize(t, 1024, ClampScreenWidthToGrid(1024, breakPoints))
assertSize(t, 1440, ClampScreenWidthToGrid(1440, breakPoints))
assertSize(t, 1440, ClampScreenWidthToGrid(1441, breakPoints))
assertSize(t, 1440, ClampScreenWidthToGrid(10000, breakPoints))
assertSize(t, 320, clampScreenWidthToGrid(298, breakPoints))
assertSize(t, 768, clampScreenWidthToGrid(321, breakPoints))
assertSize(t, 768, clampScreenWidthToGrid(766, breakPoints))
assertSize(t, 1024, clampScreenWidthToGrid(1024, breakPoints))
assertSize(t, 1440, clampScreenWidthToGrid(1440, breakPoints))
assertSize(t, 1440, clampScreenWidthToGrid(1441, breakPoints))
assertSize(t, 1440, clampScreenWidthToGrid(10000, breakPoints))
}

View File

@ -2,17 +2,18 @@ package handler
import (
"encoding/json"
"github.com/foomo/gofoomo/proxy/utils"
"github.com/foomo/gofoomo/rpc"
"io"
"io/ioutil"
"net/http"
"net/url"
"reflect"
"strings"
"github.com/foomo/gofoomo/proxy/utils"
"github.com/foomo/gofoomo/rpc"
)
// This handler helps you to hijack foomo rpc services. Actually it is even
// RPC helps you to hijack foomo rpc services. Actually it is even
// better, you can hijack them method by method.
//
// f := gofoomo.NewFoomo("/var/www/myApp", "test")
@ -27,6 +28,7 @@ type RPC struct {
serviceObject interface{}
}
// NewRPC rpc constructor, path is the path in the url, that you intend to hijack
func NewRPC(serviceObject interface{}, path string) *RPC {
rpc := new(RPC)
rpc.path = path
@ -42,9 +44,8 @@ func (r *RPC) getMethodFromPath(path string) string {
parts := strings.Split(r.getApplicationPath(path), "/")
if len(parts) > 0 {
return strings.ToUpper(parts[0][0:1]) + parts[0][1:]
} else {
return ""
}
return ""
}
func (r *RPC) handlesMethod(methodName string) bool {
@ -55,6 +56,7 @@ func (r *RPC) handlesPath(path string) bool {
return strings.HasPrefix(path, r.path) && r.handlesMethod(r.getMethodFromPath(path))
}
// HandlesRequest implementation of request handler interface
func (r *RPC) HandlesRequest(incomingRequest *http.Request) bool {
return incomingRequest.Method == "POST" && r.handlesPath(incomingRequest.URL.Path)
}
@ -93,9 +95,8 @@ func extractPostData(incomingRequest *http.Request) map[string]interface{} {
}
if len(body) > 0 {
return jsonDecode(body).(map[string]interface{})
} else {
return make(map[string]interface{})
}
return make(map[string]interface{})
}
func jsonDecode(jsonData []byte) (data interface{}) {

View File

@ -1,9 +1,10 @@
package handler
import (
"github.com/foomo/gofoomo/rpc"
"log"
"testing"
"github.com/foomo/gofoomo/rpc"
)
type TestService struct {

View File

@ -1,46 +1,46 @@
package handler
import (
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/proxy/utils"
"net/http"
"os"
"strings"
"time"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/gofoomo/proxy/utils"
)
// Handles serving static files from the local file system. It knows about
// StaticFiles handles serving static files from the local file system. It knows about
// foomos hierarchy and serves files from the htdocs directories of modules.
// Currently it will also serve files of disabled modules.
type StaticFiles struct {
foomo *foomo.Foomo
}
// NewStaticFiles constructor
func NewStaticFiles(foomo *foomo.Foomo) *StaticFiles {
sf := new(StaticFiles)
sf.foomo = foomo
return sf
}
// HandlesRequest request handler implementation
func (files *StaticFiles) HandlesRequest(incomingRequest *http.Request) bool {
if strings.HasPrefix(incomingRequest.URL.Path, "/foomo/modulesVar/") {
return true
}
if strings.HasPrefix(incomingRequest.URL.Path, "/foomo/modules/") {
parts := strings.Split(incomingRequest.URL.Path, "/")
if len(parts) > 3 {
moduleNameParts := strings.Split(parts[3], "-")
if strings.HasSuffix(parts[len(parts)-1], ".php") {
return false
} else {
return fileExists(files.foomo.GetModuleHtdocsDir(moduleNameParts[0]) + "/" + strings.Join(parts[4:], "/"))
}
} else {
return false
return fileExists(files.foomo.GetModuleHtdocsDir(moduleNameParts[0]) + "/" + strings.Join(parts[4:], "/"))
}
} else if strings.HasPrefix(incomingRequest.URL.Path, "/foomo/modulesVar/") {
return true
} else {
return false
}
return false
}
func fileExists(filename string) bool {
@ -76,26 +76,14 @@ func (files *StaticFiles) ServeHTTP(w http.ResponseWriter, incomingRequest *http
panicOnErr(err)
//const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
w.Header().Set("Expires", time.Now().Add(time.Hour*24*365).Format(http.TimeFormat))
// should we really compress all static file types ?!
if compress && strings.Contains(incomingRequest.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
crw := utils.NewCompressedResponseWriter(w)
defer crw.Close()
w = crw
}
http.ServeContent(w, incomingRequest, f.Name(), fileInfo.ModTime(), f)
/* if compress {
err := utils.ServeCompressed(w, incomingRequest, func(writer io.Writer) error {
_, err := io.Copy(writer, f)
return err
})
panicOnErr(err)
} else {
_, err := io.Copy(w, f)
panicOnErr(err)
}
*/
}
func getContentType(path string) (string, bool) {

View File

@ -8,18 +8,22 @@ import (
"net/http/httputil"
"github.com/foomo/gofoomo/foomo"
"github.com/foomo/tlsconfig"
)
// Handler proxy handler
type Handler interface {
HandlesRequest(incomingRequest *http.Request) bool
ServeHTTP(w http.ResponseWriter, incomingRequest *http.Request)
}
// Listener deprecated
type Listener interface {
ListenServeHTTPStart(w http.ResponseWriter, incomingRequest *http.Request) http.ResponseWriter
ListenServeHTTPDone(w http.ResponseWriter, incomingRequest *http.Request)
}
// Proxy foomo proxy
type Proxy struct {
foomo *foomo.Foomo
ReverseProxy *httputil.ReverseProxy
@ -29,13 +33,15 @@ type Proxy struct {
ServeHTTPFunc func(http.ResponseWriter, *http.Request)
}
type ProxyServer struct {
// Server server for Proxy
type Server struct {
Proxy *Proxy
Config *Config
TLSConfig *tls.Config
Foomo *foomo.Foomo
}
// NewProxy constructor
func NewProxy(f *foomo.Foomo) *Proxy {
proxy := &Proxy{
foomo: f,
@ -50,8 +56,9 @@ func (proxy *Proxy) ServeHTTP(w http.ResponseWriter, incomingRequest *http.Reque
}
func (proxy *Proxy) serveHTTP(w http.ResponseWriter, incomingRequest *http.Request) {
if proxy.auth != nil && len(proxy.auth.Domain) > 0 && !proxy.foomo.BasicAuthForRequest(w, incomingRequest, proxy.auth.Domain, proxy.auth.Realm, "access denied") {
return
if proxy.auth != nil && len(proxy.auth.Domain) > 0 {
//&& !proxy.foomo.BasicAuthForRequest(w, incomingRequest, proxy.auth.Domain, proxy.auth.Realm, "access denied") {
}
for _, listener := range proxy.listeners {
w = listener.ListenServeHTTPStart(w, incomingRequest)
@ -72,82 +79,44 @@ func (proxy *Proxy) serveHTTP(w http.ResponseWriter, incomingRequest *http.Reque
}
// AddHandler add a handler
func (proxy *Proxy) AddHandler(handler Handler) {
proxy.handlers = append(proxy.handlers, handler)
}
// AddListener deprecated
func (proxy *Proxy) AddListener(listener Listener) {
proxy.listeners = append(proxy.listeners, listener)
}
func NewProxyServerWithConfig(filename string) (p *ProxyServer, err error) {
// NewServerWithConfig constructor with a config file
func NewServerWithConfig(filename string) (p *Server, err error) {
config, err := ReadConfig(filename)
if err != nil {
return nil, err
}
return NewProxyServer(config)
return NewServer(config)
}
func NewProxyServer(config *Config) (p *ProxyServer, err error) {
proxyServer := new(ProxyServer)
proxyServer.Config = config
// NewServer constructor with config struct
func NewServer(config *Config) (p *Server, err error) {
p = &Server{
Config: config,
}
f, err := foomo.NewFoomo(config.Foomo.Dir, config.Foomo.RunMode, config.Foomo.Address)
if err != nil {
return nil, err
}
proxyServer.Foomo = f
proxyServer.Proxy = NewProxy(proxyServer.Foomo)
proxyServer.Proxy.auth = config.Server.Auth
proxyServer.TLSConfig = setupTLSConfig(proxyServer.Config.Server.TLS)
return proxyServer, nil
p.Foomo = f
p.Proxy = NewProxy(p.Foomo)
p.Proxy.auth = config.Server.Auth
p.TLSConfig = tlsconfig.NewServerTLSConfig(p.Config.Server.TLS.Mode)
return p, nil
}
func setupTLSConfig(tlsConfig TLS) *tls.Config {
c := &tls.Config{}
switch tlsConfig.Mode {
case TLSModeDefault:
// will not touch this one, but trust the golang team
case TLSModeLoose:
c.MinVersion = tls.VersionTLS10
c.CipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
tls.TLS_RSA_WITH_AES_128_CBC_SHA,
}
c.CurvePreferences = []tls.CurveID{
tls.CurveP256,
tls.CurveP384,
tls.CurveP521,
}
case TLSModeStrict:
c.MinVersion = tls.VersionTLS12
c.PreferServerCipherSuites = true
c.CipherSuites = []uint16{
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
}
c.CurvePreferences = []tls.CurveID{
tls.CurveP256,
tls.CurveP384,
tls.CurveP521,
}
}
return c
}
func (p *ProxyServer) ListenAndServe() error {
// ListenAndServe until things go bad, depending upon configuration this will\
// listen to http and https requests
func (p *Server) ListenAndServe() error {
c := p.Config.Server
errorChan := make(chan error)
startedHTTPS := false
@ -161,7 +130,6 @@ func (p *ProxyServer) ListenAndServe() error {
TLSConfig: p.TLSConfig,
}
errorChan <- tlsServer.ListenAndServeTLS(c.TLS.CertFile, c.TLS.KeyFile)
// errorChan <- http.ListenAndServeTLS(c.TLS.Address, c.TLS.CertFile, c.TLS.KeyFile, p.Proxy)
}()
startedHTTPS = true
}

View File

@ -2,16 +2,16 @@ package utils
import (
"compress/gzip"
//"io"
"net/http"
//"strings"
)
// CompressedResponseWriter helper to write compressed responses
type CompressedResponseWriter struct {
responseWriter http.ResponseWriter
gz *gzip.Writer
}
// NewCompressedResponseWriter constructor
func NewCompressedResponseWriter(responseWriter http.ResponseWriter) *CompressedResponseWriter {
crw := &CompressedResponseWriter{
responseWriter: responseWriter,
@ -45,6 +45,7 @@ func (crw *CompressedResponseWriter) WriteHeader(code int) {
crw.responseWriter.WriteHeader(code)
}
// Close me please
func (crw *CompressedResponseWriter) Close() {
crw.gz.Close()
}

View File

@ -7,6 +7,7 @@ import (
"strings"
)
// ServeCompressed serve a request with a compressed response, if the client accepts it
func ServeCompressed(w http.ResponseWriter, incomingRequest *http.Request, writeCallback func(writer io.Writer) error) error {
var writer io.Writer
writer = w
@ -20,8 +21,10 @@ func ServeCompressed(w http.ResponseWriter, incomingRequest *http.Request, write
}
// Resource304 vo
type Resource304 struct {
Etag string
}
// Handle304 304 handler
func Handle304(r *http.Request) {}

View File

@ -1,10 +1,10 @@
package rpc
// from php class Foomo\Services\RPC\Protocol\Call\MethodCall
// MethodCall from php class Foomo\Services\RPC\Protocol\Call\MethodCall
// serializing a method call
type MethodCall struct {
// id of the method call
Id string `json:"id"`
ID string `json:"id"`
// name of the method to be called
Method string `json:"method"`
// the method call arguments
@ -14,11 +14,11 @@ type MethodCall struct {
} `json:"arguments"`
}
// from php class Foomo\Services\RPC\Protocol\Reply\MethodReply
// MethodReply from php class Foomo\Services\RPC\Protocol\Reply\MethodReply
// reply to a method call
type MethodReply struct {
// id of the method call
Id string `json:"id"`
ID string `json:"id"`
// return value
Value interface{} `json:"value"`
// server side exception

View File

@ -1 +0,0 @@
package utils