diff --git a/address/handler/address.go b/address/handler/address.go index 696d559..e145f76 100644 --- a/address/handler/address.go +++ b/address/handler/address.go @@ -13,7 +13,7 @@ import ( ) var ( - AddressURL = "https://ws.postcoder.com/pcw/" + AddressURL = "https://api.ideal-postcodes.co.uk/v1/" ) type Address struct { @@ -29,7 +29,7 @@ func field(key string, vals map[string]interface{}) string { } func (a *Address) lookupPostcode(q string, rsp interface{}) error { - u := fmt.Sprintf("%s/%s/address/uk/%s?format=json&lines=2", a.Url, a.Key, q) + u := fmt.Sprintf("%saddresses?api_key=%s&postcode=%s", a.Url, a.Key, q) return api.Get(u, rsp) } @@ -53,26 +53,28 @@ func (a *Address) LookupPostcode(ctx context.Context, req *pb.LookupPostcodeRequ return nil } - var resp []interface{} + var resp map[string]interface{} // lookup the address api for the given postcode - if err := a.lookupPostcode(req.Postcode, &resp); err != nil { + if err := a.lookupPostcode(postcode, &resp); err != nil { logger.Errorf("Failed to lookup postcode %v: %v", req.Postcode, err) return errors.InternalServerError("address.lookup-postcode", "failed to lookup postcode") } - for _, res := range resp { + result := resp["result"].(map[string]interface{}) + hits := result["hits"].([]interface{}) + + for _, res := range hits { addr := res.(map[string]interface{}) rsp.Addresses = append(rsp.Addresses, &pb.Record{ - LineOne: field("addressline1", addr), - LineTwo: field("addressline2", addr), - Summary: field("summaryline", addr), - Organisation: field("organisation", addr), - BuildingName: field("buildingname", addr), + LineOne: field("line_1", addr), + LineTwo: field("line_2", addr), + Organisation: field("organisation_name", addr), + BuildingName: field("building_name", addr), Premise: field("premise", addr), - Street: field("street", addr), - Locality: field("dependentlocality", addr), - Town: field("posttown", addr), + Street: field("thoroughfare", addr), + Locality: field("dependent_locality", addr), + Town: field("post_town", addr), County: field("county", addr), Postcode: field("postcode", addr), }) diff --git a/address/handler/postcoder.go b/address/handler/postcoder.go new file mode 100644 index 0000000..578612c --- /dev/null +++ b/address/handler/postcoder.go @@ -0,0 +1,78 @@ +package handler + +import ( + "context" + "fmt" + "strings" + + "github.com/micro/micro/v3/service/errors" + "github.com/micro/micro/v3/service/logger" + "github.com/micro/micro/v3/service/store" + pb "github.com/micro/services/address/proto" + "github.com/micro/services/pkg/api" +) + +var ( + PostcoderURL = "https://ws.postcoder.com/pcw/" +) + +type Postcoder struct { + Url string + Key string +} + +func (a *Postcoder) lookupPostcode(q string, rsp interface{}) error { + u := fmt.Sprintf("%s/%s/address/uk/%s?format=json&lines=2", a.Url, a.Key, q) + return api.Get(u, rsp) +} + +func (a *Postcoder) LookupPostcode(ctx context.Context, req *pb.LookupPostcodeRequest, rsp *pb.LookupPostcodeResponse) error { + if len(req.Postcode) == 0 { + return errors.BadRequest("address.lookup-postcode", "missing postcode") + } + + // check the store to see if we have it already + postcode := strings.ToLower(req.Postcode) + postcode = strings.ReplaceAll(postcode, " ", "") + + // check the store + rec, err := store.Read(postcode) + if err == nil && len(rec) > 0 { + for _, r := range rec { + var records []*pb.Record + r.Decode(&records) + rsp.Addresses = records + } + return nil + } + + var resp []interface{} + + // lookup the address api for the given postcode + if err := a.lookupPostcode(req.Postcode, &resp); err != nil { + logger.Errorf("Failed to lookup postcode %v: %v", req.Postcode, err) + return errors.InternalServerError("address.lookup-postcode", "failed to lookup postcode") + } + + for _, res := range resp { + addr := res.(map[string]interface{}) + rsp.Addresses = append(rsp.Addresses, &pb.Record{ + LineOne: field("addressline1", addr), + LineTwo: field("addressline2", addr), + Summary: field("summaryline", addr), + Organisation: field("organisation", addr), + BuildingName: field("buildingname", addr), + Premise: field("premise", addr), + Street: field("street", addr), + Locality: field("dependentlocality", addr), + Town: field("posttown", addr), + County: field("county", addr), + Postcode: field("postcode", addr), + }) + } + + // cache the record if we haven't done so already + store.Write(store.NewRecord(postcode, rsp.Addresses)) + + return nil +}