55 lines
1.2 KiB
Go
55 lines
1.2 KiB
Go
package funker
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"net"
|
|
"reflect"
|
|
)
|
|
|
|
// Handle a Funker function.
|
|
func Handle(handler interface{}) error {
|
|
handlerValue := reflect.ValueOf(handler)
|
|
handlerType := handlerValue.Type()
|
|
if handlerType.Kind() != reflect.Func || handlerType.NumIn() != 1 || handlerType.NumOut() != 1 {
|
|
return fmt.Errorf("Handler must be a function with a single parameter and single return value.")
|
|
}
|
|
argsValue := reflect.New(handlerType.In(0))
|
|
|
|
listener, err := net.Listen("tcp", ":9999")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
conn, err := listener.Accept()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// We close listener, because we only allow single request.
|
|
// Note that TCP "backlog" cannot be used for that purpose.
|
|
// http://www.perlmonks.org/?node_id=940662
|
|
if err = listener.Close(); err != nil {
|
|
return err
|
|
}
|
|
argsJSON, err := ioutil.ReadAll(conn)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
err = json.Unmarshal(argsJSON, argsValue.Interface())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ret := handlerValue.Call([]reflect.Value{argsValue.Elem()})[0].Interface()
|
|
retJSON, err := json.Marshal(ret)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if _, err = conn.Write(retJSON); err != nil {
|
|
return err
|
|
}
|
|
|
|
return conn.Close()
|
|
}
|