Skip to content

Instantly share code, notes, and snippets.

@SamWhited
Last active August 29, 2015 13:58
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save SamWhited/9941159 to your computer and use it in GitHub Desktop.
A simple server that accepts HTTP post requests

This is a simple server example that accepts geojson features as POST requests (fair warning, it does no validation to make sure anything is geojson conformant) and spits out a geojson file with all the features wrapped in a feature array.

This is just an example. It does lots of bad things (like reading / writing the entire file every time it gets a post request) and is easily abused. The authentication isn't exactly secure either. By default it listens on :2230.

package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
)
const (
API_KEY string = "your api key"
FILE_NAME string = "data.geojson"
)
func writeResp(rw http.ResponseWriter, status int, message string, err error) {
rw.WriteHeader(status)
rw.Write([]byte(message))
fmt.Println(message, err)
}
func post(rw http.ResponseWriter, req *http.Request) {
location := req.FormValue("location")
json_type := req.FormValue("type")
api_key := req.FormValue("api_key")
if api_key == API_KEY {
checkin := make(map[string]interface{})
err := json.Unmarshal([]byte(location), &checkin)
if err != nil {
writeResp(rw, http.StatusBadRequest, "Invalid JSON.", err)
return
}
fmt.Println(location)
geojson := make(map[string]interface{})
if data, err := ioutil.ReadFile(FILE_NAME); err == nil {
json.Unmarshal(data, &geojson)
}
// If the features array does not exist, make it.
if _, ok := geojson["features"]; !ok {
geojson["features"] = make([]interface{}, 0)
}
if val, ok := geojson["type"]; !ok || val != "FeatureCollection" {
geojson["type"] = "FeatureCollection"
}
switch json_type {
case "Feature":
geojson["features"] = append(geojson["features"].([]interface{}), checkin)
case "FeatureCollection":
geojson["features"] = append(geojson["features"].([]interface{}), checkin["features"].([]interface{})...)
case "Unknown":
writeResp(rw, http.StatusBadRequest, "Unknown type.", err)
return
}
newjson, err := json.Marshal(geojson)
if err != nil {
writeResp(rw, http.StatusInternalServerError, "Error creating json.", err)
return
}
err = ioutil.WriteFile(FILE_NAME, newjson, os.FileMode(0644))
if err != nil {
writeResp(rw, http.StatusInternalServerError, "Error writing json.", err)
return
}
rw.Write([]byte("Success!"))
} else {
fmt.Println("Invalid API key:", api_key)
rw.WriteHeader(http.StatusUnauthorized)
rw.Write([]byte("Forbidden."))
}
}
func get(rw http.ResponseWriter, req *http.Request) {
if data, err := ioutil.ReadFile(FILE_NAME); err == nil {
rw.Write(data)
} else {
message := "There was an error reading the file…"
fmt.Println(message, err)
rw.WriteHeader(http.StatusNotFound)
rw.Write([]byte(message))
}
}
func handler(rw http.ResponseWriter, req *http.Request) {
switch req.Method {
case "POST":
post(rw, req)
case "GET":
get(rw, req)
}
}
func main() {
fmt.Println("Listening on http://0.0.0.0:2230")
err := http.ListenAndServe(":2230", http.HandlerFunc(handler))
if err != nil {
fmt.Println(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment