Full API implementation
This commit is contained in:
@@ -3,43 +3,53 @@ package controllers
|
|||||||
import (
|
import (
|
||||||
"addrss/pkg/postal"
|
"addrss/pkg/postal"
|
||||||
"addrss/pkg/router"
|
"addrss/pkg/router"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Api struct{}
|
type Api struct{}
|
||||||
|
|
||||||
type ParseRequest struct {
|
|
||||||
Address string `json:"address"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a Api) AddRoutes() {
|
func (a Api) AddRoutes() {
|
||||||
router.AddPost("/v1/expand", expandAddress).Anonymous()
|
router.AddGet("/suggestions", suggestions).Anonymous()
|
||||||
router.AddPost("/v1/parse", parseAddress).Anonymous()
|
router.AddGet("/parse", parse).Anonymous()
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandAddress(ctx *router.Context) {
|
func suggestions(ctx *router.Context) {
|
||||||
expansions := postal.ExpandAddress("1080 Brayden Ct. Hebron KY 41048")
|
address, err := ctx.Request.Query("address")
|
||||||
for i := 0; i < len(expansions); i++ {
|
if err != nil {
|
||||||
fmt.Println(expansions[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.Response.NoContent()
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAddress(ctx *router.Context) {
|
|
||||||
pr := ParseRequest{}
|
|
||||||
if err := ctx.Request.Bind(&pr); err != nil {
|
|
||||||
ctx.Response.BadRequest(err)
|
ctx.Response.BadRequest(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
options := postal.ParserOptions{}
|
var parsedSlice []map[string]any
|
||||||
|
|
||||||
pa := postal.ParseAddressOptions(pr.Address, options)
|
expansions := postal.ExpandAddress(address.(string))
|
||||||
|
for i := 0; i < len(expansions); i++ {
|
||||||
|
parsed := parseAddress(expansions[i])
|
||||||
|
parsedSlice = append(parsedSlice, parsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Response.OK(parsedSlice)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parse(ctx *router.Context) {
|
||||||
|
address, err := ctx.Request.Query("address")
|
||||||
|
if err != nil {
|
||||||
|
ctx.Response.BadRequest(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed := parseAddress(address.(string))
|
||||||
|
ctx.Response.OK(parsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseAddress(address string) map[string]any {
|
||||||
|
pa := postal.ParseAddress(address)
|
||||||
addr := map[string]any{}
|
addr := map[string]any{}
|
||||||
|
|
||||||
for i := 0; i < len(pa); i++ {
|
for i := 0; i < len(pa); i++ {
|
||||||
|
// This is hacky, but renaming in libpostal involves retraining the model.
|
||||||
|
if pa[i].Label == "postcode" {
|
||||||
|
pa[i].Label = "zip_code"
|
||||||
|
}
|
||||||
addr[pa[i].Label] = pa[i].Value
|
addr[pa[i].Label] = pa[i].Value
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Response.OK(addr)
|
return addr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"addrss/pkg/router"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Guestbook struct{}
|
|
||||||
|
|
||||||
type guestbookError struct {
|
|
||||||
Fields []string `json:"fields"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g Guestbook) AddRoutes() {
|
|
||||||
router.AddPost("/guestbook", signGuestbook).Anonymous()
|
|
||||||
}
|
|
||||||
|
|
||||||
func signGuestbook(ctx *router.Context) {
|
|
||||||
//gb := ctx.Request.Model.(repo.Guestbook)
|
|
||||||
|
|
||||||
ctx.Response.NoContent()
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,36 +16,44 @@ type Request struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (req Request) Param(key string) (any, error) {
|
func (req Request) Param(key string) (any, error) {
|
||||||
value, ok := req.params[key]
|
if value, ok := req.params[key]; ok {
|
||||||
if ok {
|
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("param %s not found", key)
|
return nil, fmt.Errorf("param %s not found", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req Request) ParamInt64(key string) (int64, error) {
|
func (req Request) Query(key string) (any, error) {
|
||||||
param, err := req.Param(key)
|
values, err := url.ParseQuery(req.Request.URL.RawQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
i, err := strconv.Atoi(param.(string))
|
value, ok := values[key]
|
||||||
if err != nil {
|
if !ok {
|
||||||
return 0, err
|
return nil, fmt.Errorf("query string parameter %s not found", key)
|
||||||
}
|
}
|
||||||
|
|
||||||
return int64(i), nil
|
if len(value) > 1 {
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return value[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind Binds the request body to the struct pointer v using the Content-Type header to select a binder. This function panics if v cannot be bound.
|
// Bind Binds the request body to the struct pointer v using the Content-Type header to select a binder.
|
||||||
func (req Request) Bind(v any) error {
|
func (req Request) Bind(v any) error {
|
||||||
|
body, err := req.Request.GetBody()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
mime := req.Header.Get("Content-Type")
|
mime := req.Header.Get("Content-Type")
|
||||||
mime = strings.Split(mime, ";")[0]
|
mime = strings.Split(mime, ";")[0]
|
||||||
|
|
||||||
switch mime {
|
switch mime {
|
||||||
case "application/json":
|
case "application/json":
|
||||||
err := json.NewDecoder(req.Body).Decode(&v)
|
err := json.NewDecoder(body).Decode(&v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error while decoding http request body as json: %w", err)
|
return fmt.Errorf("error while decoding http request body as json: %w", err)
|
||||||
}
|
}
|
||||||
@@ -57,13 +65,13 @@ func (req Request) Bind(v any) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req Request) FormFile(key string) (multipart.File, *multipart.FileHeader, error) {
|
func (req Request) File(key string) (multipart.File, *multipart.FileHeader, error) {
|
||||||
maxMegs, err := config.GetInt64("uploads.maxMegabytes")
|
maxMegs, err := config.GetInt64("uploads.maxMegabytes")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
maxMegs = 8000000
|
maxMegs = 8000000
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := req.ParseMultipartForm(maxMegs << 20); err != nil {
|
if err = req.ParseMultipartForm(maxMegs << 20); err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user