Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Idiomatic go #21

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties

17 changes: 10 additions & 7 deletions base_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gottp

import "net/http"

//Handler is an interface that implements all the methods of an HTTP Request.
type Handler interface {
Get(request *Request)
Put(request *Request)
Expand All @@ -12,6 +13,8 @@ type Handler interface {
Patch(request *Request)
}

//BaseHandler is a type that has a name and a pattern to match.
//This type will implement the required methods of Handler interface.
type BaseHandler struct {
name string
pattern string
Expand All @@ -22,30 +25,30 @@ func notImplemented(request *Request) {
request.Raise(e)
}

func (self *BaseHandler) Get(request *Request) {
func (b *BaseHandler) Get(request *Request) {
notImplemented(request)
}

func (self *BaseHandler) Put(request *Request) {
func (b *BaseHandler) Put(request *Request) {
notImplemented(request)
}

func (self *BaseHandler) Post(request *Request) {
func (b *BaseHandler) Post(request *Request) {
notImplemented(request)
}

func (self *BaseHandler) Delete(request *Request) {
func (b *BaseHandler) Delete(request *Request) {
notImplemented(request)
}

func (self *BaseHandler) Head(request *Request) {
func (b *BaseHandler) Head(request *Request) {
notImplemented(request)
}

func (self *BaseHandler) Options(request *Request) {
func (b *BaseHandler) Options(request *Request) {
notImplemented(request)
}

func (self *BaseHandler) Patch(request *Request) {
func (b *BaseHandler) Patch(request *Request) {
notImplemented(request)
}
5 changes: 5 additions & 0 deletions conf/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (
"code.google.com/p/gcfg"
)

// Configurer interface implements two methods
type Configurer interface {
MakeConfig(string)
GetGottpConfig() *GottpSettings
}

//ReadConfig takes a configString, and a Configurer, it dumps the data from the string
//to corresponding feilds in the Configurer.
func ReadConfig(configString string, cfg Configurer) error {
err := gcfg.ReadStringInto(cfg, configString)
if err != nil {
Expand All @@ -20,6 +23,8 @@ func ReadConfig(configString string, cfg Configurer) error {
return err
}

//MakeConfig takes a configPath and a Congigurer, it dumps the data from the file
//to corresponding feilds in the Configurer.
func MakeConfig(configPath string, cfg Configurer) {
if _, err := os.Stat(configPath); os.IsNotExist(err) {
panic("no such file or directory: " + configPath)
Expand Down
2 changes: 2 additions & 0 deletions conf/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"log"
)

// CliArgs returns filepath and socket address, if either or both the
// commandline arguments are called.
func CliArgs() (string, string) {
var unixSocketptr = flag.String(
"UNIX_SOCKET",
Expand Down
18 changes: 13 additions & 5 deletions conf/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package conf

//GottpSettings is a structure representatng all the setting, including listening address and port number
type GottpSettings struct {
EmailHost string
EmailPort string
Expand All @@ -16,17 +17,24 @@ const baseConfig = `;Sample Configuration File
[gottp]
listen="127.0.0.1:8005";`

//Config is a structure that wraps GottpSettings for Configurations
//It implements both MakeConfig and GetConfig making it Configurer
type Config struct {
Gottp GottpSettings
}

func (self *Config) MakeConfig(configPath string) {
ReadConfig(baseConfig, self)
//MakeConfig takes the file path as configPath and returns with data filled
//into corresponding feilds of the Config struct.
//After a call to this function, Config.Gottp is populated with appropriate
//values.
func (c *Config) MakeConfig(configPath string) {
ReadConfig(baseConfig, c)
if configPath != "" {
MakeConfig(configPath, self)
MakeConfig(configPath, c)
}
}

func (self *Config) GetGottpConfig() *GottpSettings {
return &self.Gottp
//GetGottpConfig returns pointer to GottpSettings
func (c *Config) GetGottpConfig() *GottpSettings {
return &c.Gottp
}
1 change: 1 addition & 0 deletions global_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"
)

// GlobalHandler handles all requests for "/".
func GlobalHandler(w http.ResponseWriter, req *http.Request) {
defer timeTrack(time.Now(), req)
request := Request{Writer: w, Request: req}
Expand Down
89 changes: 89 additions & 0 deletions methods_implemented.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package gottp

import (
"encoding/json"
"net/http"

"github.com/parnurzeal/gorequest"
)

func methondImplemented(u *Url) {
u.methodsImplemented = append(u.methodsImplemented, "OPTIONS")
if u.name == "async_pipe" || u.name == "urls" || u.name == "pipe" {
return
}
methodsSupported := []string{"GET", "PUT", "POST", "DELETE", "HEAD", "OPTIONS", "PATCH"}
url := "http://" + Address() + u.url
client := gorequest.New()
for _, method := range methodsSupported {
switch method {
case "GET":
resp, _, err := client.Get(url).End()
if err == nil {
if resp.StatusCode == http.StatusOK {
var data map[string]int
json.NewDecoder(resp.Body).Decode(&data)
if data["status"] != 501 && data["status"] != 0 {
u.methodsImplemented = append(u.methodsImplemented, method)
}
}
}
case "POST":
resp, _, err := client.Post(url).End()
if err == nil {
if resp.StatusCode == http.StatusOK {
var data map[string]int
json.NewDecoder(resp.Body).Decode(&data)
if data["status"] != 501 && data["status"] != 0 {
u.methodsImplemented = append(u.methodsImplemented, method)
}
}
}
case "PUT":
resp, _, err := client.Put(url).End()
if err == nil {
if resp.StatusCode == http.StatusOK {
var data map[string]int
json.NewDecoder(resp.Body).Decode(&data)
if data["status"] != 501 && data["status"] != 0 {
u.methodsImplemented = append(u.methodsImplemented, method)
}
}
}
case "DELETE":
resp, _, err := client.Delete(url).End()
if err == nil {
if resp.StatusCode == http.StatusOK {
var data map[string]int
json.NewDecoder(resp.Body).Decode(&data)
if data["status"] != 501 && data["status"] != 0 {
u.methodsImplemented = append(u.methodsImplemented, method)
}
}
}
case "HEAD":
resp, _, err := client.Head(url).End()
if err == nil {
if resp.StatusCode == http.StatusOK {
var data map[string]int
json.NewDecoder(resp.Body).Decode(&data)
if data["status"] != 501 && data["status"] != 0 {
u.methodsImplemented = append(u.methodsImplemented, method)
}
}
}
case "PATCH":
resp, _, err := client.Patch(url).End()
if err == nil {
if resp.StatusCode == http.StatusOK {
var data map[string]int
json.NewDecoder(resp.Body).Decode(&data)
if data["status"] != 501 && data["status"] != 0 {
u.methodsImplemented = append(u.methodsImplemented, method)
}
}
}
}
}
return
}
24 changes: 23 additions & 1 deletion request.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ func makeString(val interface{}) (ret string) {
return
}

// Request type is a gottp wrapper of the incoming request and its
// response. It has data structures for url arguments or parameters.
type Request struct {
Request *http.Request
Writer http.ResponseWriter
Expand All @@ -68,6 +70,7 @@ type Request struct {
params *utils.Q
}

// makeUrlArgs returns map of url arguments.
func (r *Request) makeUrlArgs(params utils.Q) {
if r.UrlArgs != nil {
for key, value := range *r.UrlArgs {
Expand All @@ -76,6 +79,8 @@ func (r *Request) makeUrlArgs(params utils.Q) {
}
}

// GetPaginator returns pointer to Paginator type with appropriate values
// assigned.
func (r *Request) GetPaginator() *Paginator {
p := Paginator{Limit: -1}
qp := r.GetArguments()
Expand Down Expand Up @@ -109,6 +114,7 @@ func (r *Request) GetPaginator() *Paginator {
return &p
}

// makeUrlParams returns map of url parameters.
func (r *Request) makeUrlParams(params utils.Q) {
r.Request.ParseForm()
for key, value := range r.Request.Form {
Expand All @@ -121,13 +127,16 @@ func (r *Request) makeUrlParams(params utils.Q) {
}
}

// makeBodyParams returns map of body parameters.
func (r *Request) makeBodyParams(params utils.Q) {
//if (r.Request.Method == "PUT" || r.Request.Method == "POST") {
if r.Request.ContentLength != 0 {
utils.DecodeStream(r.Request.Body, &params)
}
}

// GetArguments returns pointer to request's param which
// is a map of all the parameters/arguments in the url/body.
func (r *Request) GetArguments() *utils.Q {
if r.params == nil {
params := utils.Q{}
Expand All @@ -140,34 +149,42 @@ func (r *Request) GetArguments() *utils.Q {
return r.params
}

// ConvertArguments converts the request arguments to correspondig golang data structures
// and stores it into f.
func (r *Request) ConvertArguments(f interface{}) {
utils.Convert(r.GetArguments(), f)
}

// GetArgument returns the argument value matching the key.
func (r *Request) GetArgument(key string) interface{} {
args := *r.GetArguments()
return args[key]
}

// ConvertArgument converts the value of argument matching key to correspondig golang data
// structures and stores it into f.
func (r *Request) ConvertArgument(key string, f interface{}) {
args := *r.GetArguments()
val := args[key]
utils.Convert(val, f)
}

// Finish adds three headers, and returns the corresponding JSON of data.
func (r *Request) Finish(data interface{}) []byte {
r.Writer.Header().Set("Server", serverUA)
r.Writer.Header().Set("Access-Control-Allow-Origin", "*")
r.Writer.Header().Set("Content-Type", "application/json")
return utils.Encoder(data)
}

// Redirect redirects the user to given url.
func (r *Request) Redirect(url string, status int) {
log.Println("Redirecting to", url)
http.Redirect(r.Writer, r.Request, url, status)
return
}

// Write writes and finishes the request with apporpiate response.
func (r *Request) Write(data interface{}) {
var piped utils.Q

Expand All @@ -177,6 +194,8 @@ func (r *Request) Write(data interface{}) {
piped = utils.Q{
"data": data,
"status": http.StatusOK,
// why is there a need for message field in
// the response when theres no way to change it?
"message": "",
}
}
Expand Down Expand Up @@ -207,10 +226,13 @@ func (r *Request) Write(data interface{}) {
}
}

// Raise sends HttpError as response
func (r *Request) Raise(e HttpError) {
r.Write(e)
}

// performRequest takes a handler and a pointer to request and
// calls the appropriate handler defined by the user.
func performRequest(handler Handler, p *Request) {
method := (*p).Request.Method

Expand Down Expand Up @@ -242,7 +264,7 @@ func doRequest(request *Request, availableUrls *[]*Url) {
urlArgs, err := url.MakeUrlArgs(&requestUrl)
if !err {
request.UrlArgs = urlArgs
performRequest(url.handler, request)
performRequest(url, request)
return
}
}
Expand Down
Loading