Skip to content

Commit 8269173

Browse files
authored
Merge pull request #2 from simonmartyr/fix/delivery-missing-headers
fix: 🐛 support for x-picnic-did and x-picnic-agent headers
2 parents d751f54 + db1e97f commit 8269173

5 files changed

Lines changed: 127 additions & 13 deletions

File tree

delivery_scenario_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package picnic
22

33
import (
4+
"github.com/joho/godotenv"
45
"net/http"
6+
"os"
57
"testing"
68
)
79

@@ -39,3 +41,27 @@ func TestGetDeliveryScenario_Error_MissingId(t *testing.T) {
3941
t.Error("No error raised")
4042
}
4143
}
44+
45+
func Test_Integration_Deliveries(t *testing.T) {
46+
godotenv.Load()
47+
c := New(&http.Client{},
48+
WithUsername(os.Getenv("USERNAME")),
49+
WithHashedPassword(os.Getenv("SECRET")),
50+
WithVersion("15"),
51+
)
52+
authErr := c.Authenticate()
53+
if authErr != nil {
54+
t.Error("auth failed")
55+
}
56+
deliveries, dErr := c.GetDeliveries([]DeliveryStatus{COMPLETED, CURRENT})
57+
if dErr != nil {
58+
t.Error(dErr)
59+
}
60+
pos, posErr := c.GetDeliveryPosition((*deliveries)[0].DeliveryId)
61+
if posErr != nil {
62+
t.Fatal(posErr)
63+
}
64+
if pos == nil {
65+
t.Error("invalid pos")
66+
}
67+
}

picnic.go

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,18 @@ import (
1515

1616
// Client the picnic api client it is recommended to use the New method to create a new instance
1717
type Client struct {
18-
http *http.Client
19-
baseURL string
20-
version string
21-
country string
22-
token string
23-
username string
24-
secret string
18+
http *http.Client
19+
baseURL string
20+
version string
21+
country string
22+
token string
23+
parsedToken *token
24+
username string
25+
secret string
2526
}
2627

28+
const appVersion = "1.15.243-18832"
29+
2730
type ClientOption func(client *Client)
2831

2932
// WithVersion specify the particular version of the picnic API you wish to use.
@@ -182,7 +185,13 @@ func (c *Client) get(url string, result interface{}) error {
182185
if requestErr != nil {
183186
return requestErr
184187
}
185-
configureHeaders(request, c.token)
188+
c.configureHeaders(request)
189+
if strings.Contains(url, "deliveries") {
190+
headerErr := c.includeAgentHeader(request)
191+
if headerErr != nil {
192+
return headerErr
193+
}
194+
}
186195
res, httpErr := c.http.Do(request)
187196
if httpErr != nil {
188197
return httpErr
@@ -207,7 +216,7 @@ func (c *Client) post(url string, body any, result interface{}) error {
207216
if requestErr != nil {
208217
return requestErr
209218
}
210-
configureHeaders(request, c.token)
219+
c.configureHeaders(request)
211220
res, httpErr := c.http.Do(request)
212221
if httpErr != nil {
213222
return httpErr
@@ -263,7 +272,19 @@ func makeUrl(countryCode string, version string) string {
263272
return fmt.Sprintf("https://storefront-prod.%s.picnicinternational.com/api/%s", countryCode, version)
264273
}
265274

266-
func configureHeaders(request *http.Request, token string) {
267-
request.Header.Set("x-picnic-auth", token)
275+
func (c *Client) configureHeaders(request *http.Request) {
276+
request.Header.Set("x-picnic-auth", c.token)
268277
request.Header.Set("Content-Type", "application/json")
269278
}
279+
280+
func (c *Client) includeAgentHeader(request *http.Request) error {
281+
if c.parsedToken == nil {
282+
err := c.parseJwt()
283+
if err != nil {
284+
return err
285+
}
286+
}
287+
request.Header.Set("x-picnic-agent", fmt.Sprintf("%d;%s;", c.parsedToken.PcClid, appVersion))
288+
request.Header.Set("x-picnic-did", c.parsedToken.PcDid)
289+
return nil
290+
}

picnic_test.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"testing"
1010
)
1111

12+
const mockToken = `fakeheader.eyJzdWIiOiI4MDgtODEwLTAzMzkiLCJwYzpjbGlkIjoyMDEwMCwicGM6cHY6ZW5hYmxlZCI6ZmFsc2UsInBjOmxvZ2ludHMiOjE1NjEwNDUyNTYxMDcsImlzcyI6InBpY25pYy1kZXYiLCJwYzpwdjp2ZXJpZmllZCI6dHJ1ZSwicGM6MmZhIjoiTk9UX1JFUVVJUkVEIiwicGM6cm9sZSI6IlNUQU5EQVJEX1VTRVIiLCJwYzpkaWQiOiJCQTAyNjAxOC1GMEVFLTRDOTAtQTFENC00Q0MzNjg3RUE4ODEiLCJleHAiOjE3MjAyNjM5NzgsImlhdCI6MTcwNDcxMTk3OCwianRpIjoiMlJJN0c0UFUifQ.FakeSiganture`
13+
1214
func testClient(code int, body io.Reader, validators ...func(*http.Request)) (*Client, *httptest.Server) {
1315
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1416
for _, v := range validators {
@@ -24,7 +26,7 @@ func testClient(code int, body io.Reader, validators ...func(*http.Request)) (*C
2426
client := &Client{
2527
http: http.DefaultClient,
2628
baseURL: server.URL + "/",
27-
token: "mockToken",
29+
token: mockToken,
2830
}
2931
return client, server
3032
}
@@ -45,7 +47,7 @@ func testImageClient(code int, body io.Reader, validators ...func(*http.Request)
4547
client := &Client{
4648
http: http.DefaultClient,
4749
baseURL: server.URL + "/",
48-
token: "mockToken",
50+
token: mockToken,
4951
}
5052
return client, server
5153
}
@@ -227,6 +229,13 @@ func Test_Integration(t *testing.T) {
227229
if authErr != nil {
228230
t.Error("auth failed")
229231
}
232+
user, userErr := c.GetUser()
233+
if userErr != nil {
234+
t.Fatal(userErr)
235+
}
236+
if user == nil {
237+
t.Error("invalid user")
238+
}
230239
}
231240

232241
func Test_Logout(t *testing.T) {

token.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package picnic
2+
3+
import (
4+
"encoding/base64"
5+
"encoding/json"
6+
"errors"
7+
"strings"
8+
)
9+
10+
type token struct {
11+
Sub string `json:"sub"`
12+
PcClid int `json:"pc:clid"`
13+
PcDid string `json:"pc:did"`
14+
}
15+
16+
func (c *Client) parseJwt() error {
17+
tokenParts := strings.Split(c.token, ".")
18+
if len(tokenParts) != 3 {
19+
return errors.New("invalid token structure")
20+
}
21+
jsonContent, decodeErr := base64.RawStdEncoding.DecodeString(tokenParts[1])
22+
if decodeErr != nil {
23+
return decodeErr
24+
}
25+
var toReturn = token{}
26+
jsonErr := json.Unmarshal(jsonContent, &toReturn)
27+
if jsonErr != nil {
28+
return jsonErr
29+
}
30+
c.parsedToken = &toReturn
31+
return nil
32+
}

token_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package picnic
2+
3+
import "testing"
4+
5+
func TestParseJwt(t *testing.T) {
6+
client := &Client{
7+
token: mockToken,
8+
}
9+
tokenErr := client.parseJwt()
10+
if tokenErr != nil {
11+
t.Fatal(tokenErr)
12+
}
13+
if client.parsedToken.PcDid == "" {
14+
t.Error("PcDid invalid")
15+
}
16+
}
17+
18+
func TestParseJwtInvalid(t *testing.T) {
19+
client := &Client{
20+
token: "fakeboi",
21+
}
22+
tokenErr := client.parseJwt()
23+
if tokenErr == nil {
24+
t.Error("token should not parse")
25+
}
26+
}

0 commit comments

Comments
 (0)