package middlewares import ( "encoding/json" "strings" "github.com/gofiber/fiber/v2" ) // operatingCityPrefixes maps supported 3-digit pincode prefixes to city names. var operatingCityPrefixes = map[string]string{ "641": "Coimbatore", "600": "Chennai", "560": "Bengaluru", "500": "Hyderabad", "629": "Nagercoil", } // CityGateMiddleware rejects bookings from pincodes outside Doormile's operating cities. // It reads pickuppincode from the JSON body without consuming it, so the downstream // controller can still call c.BodyParser() as usual. func CityGateMiddleware(c *fiber.Ctx) error { var body struct { Pickuppincode string `json:"pickuppincode"` } if err := json.Unmarshal(c.Body(), &body); err != nil || body.Pickuppincode == "" { return c.Next() } pincode := strings.TrimSpace(body.Pickuppincode) if len(pincode) >= 3 { if _, ok := operatingCityPrefixes[pincode[:3]]; ok { return c.Next() } } return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ "error": "We are not yet operating in your city. Stay tuned!", "code": "CITY_NOT_SUPPORTED", }) } // PincodeInOperatingCity reports whether a pincode falls in a city Doormile // runs in, and names it. // // Exported because the customer app's booking request does not carry a // pickuppincode at all — its pickup point is a title/sub/lat/lng from the place // search, so CityGateMiddleware's body sniff finds nothing and waves it // through. A middleware that silently no-ops on the one caller it matters most // for is worse than no middleware, so the customer handler resolves the pickup // point to a pincode itself and asks this directly. func PincodeInOperatingCity(pincode string) (string, bool) { pincode = strings.TrimSpace(pincode) if len(pincode) < 3 { return "", false } city, ok := operatingCityPrefixes[pincode[:3]] return city, ok }