Page MenuHomePhabricator

httpbb with HTTP POSTs and json payload
Closed, ResolvedPublic

Description

Hi folks!

I am probably missing something with httpb, but the following config leads to an error:

elukey@deploy1002:~$ cat inference_staging.yaml 
https://enwiki-goodfaith.revscoring-editquality-goodfaith.wikimedia.org:
- path: /v1/models/enwiki-goodfaith:predict
  request_headers:
    "Content-Type": "application/json"
    "Accept-Encoding": "application/json"
  form_body: 
    "rev_id": 1234567
  assert_status: 200
  assert_body_contains: probability
  method: POST

elukey@deploy1002:~$ httpbb --host inference-staging.svc.codfw.wmnet --https_port 30443 inference_staging.yaml 
Sending to inference-staging.svc.codfw.wmnet...
https://enwiki-goodfaith.revscoring-editquality-goodfaith.wikimedia.org/v1/models/enwiki-goodfaith:predict (inference_staging.yaml:2)
    Status code: expected 200, got 400.
    Body: expected to contain 'probability', got '{"error":"Unrecognized request format: unexpected '... (87 characters total).
===
FAIL: 1 request sent to inference-staging.svc.codfw.wmnet. 1 request with failed assertions.

I tried to set up a minimal repro test case:

import requests
import json

r = requests.post('https://inference-staging.svc.codfw.wmnet:30443/v1/models/enwiki-goodfaith:predict',
                  data={'rev_id': 123456789},
                  headers={"Content-type": "application/json",
                           "Host": "enwiki-goodfaith.revscoring-editquality-goodfaith.wikimedia.org"})

print(f"Test 1: HTTP {r.status_code} and body {r.text}")

r = requests.post('https://inference-staging.svc.codfw.wmnet:30443/v1/models/enwiki-goodfaith:predict',
                  data=json.dumps({"rev_id": 123456}),
                  headers={"Content-type": "application/json",
                           "Host": "enwiki-goodfaith.revscoring-editquality-goodfaith.wikimedia.org"})

print(f"Test 2: HTTP {r.status_code} and body {r.text}")

r = requests.post('https://inference-staging.svc.codfw.wmnet:30443/v1/models/enwiki-goodfaith:predict',
                  json={'rev_id': 123456789},
                  headers={"Content-type": "application/json",
                           "Host": "enwiki-goodfaith.revscoring-editquality-goodfaith.wikimedia.org"})

print(f"Test 3: HTTP {r.status_code} and body {r.text}")

This leads to:

Test 1: HTTP 400 and body {"error":"Unrecognized request format: unexpected character: line 1 column 1 (char 0)"}
Test 2: HTTP 200 and body {"enwiki":{"models":{"goodfaith":{"version":"0.5.1"}},"scores":{"123456":{"goodfaith":{"score":{"prediction":true,"probability":{"false":0.03387957196040836,"true":0.9661204280395916}}}}}}}
Test 3: HTTP 200 and body {"enwiki":{"models":{"goodfaith":{"version":"0.5.1"}},"scores":{"123456789":{"goodfaith":{"score":{"prediction":true,"probability":{"false":0.025037544564238123,"true":0.9749624554357619}}}}}}}

Is httpbb fully supporting JSON payloads for POSTs or is there anything to be added in the config that I am missing?

Event Timeline

Change 884920 had a related patch set uploaded (by Ilias Sarantopoulos; author: Ilias Sarantopoulos):

[operations/software/httpbb@master] feat: add json payload capability

https://gerrit.wikimedia.org/r/884920

In the patch above I convert the dictionary passed in form_body field to json if there is the header Content-Type: application/json exists in the request.

Alternatively in the future - and more in line with the requests library - we could add a json_payload field in the httpb parser and add the json argument when we issue the request

self.session.request(
                    case.method, url, data=case.form_body, json=case.json_payload, headers=headers,
                    timeout=case.timeout_seconds, allow_redirects=False)

However for now chose the first option in order to be backward compatible with older versions of the requests library as the json argument was added in version 2.4.2 - More info in requests lirbray docs as at this moment httpbb requires 'requests>=2.21.0'

After discussing during the review with @RLazarus we went with the second approach.
In the aforementioned patch the tests support a json_body field in which we pass a json serializable object and the request is altered.
Only one of the form_body or json_body fields can be specified, something which is validated upon parsing the test cases.

Change 884920 merged by jenkins-bot:

[operations/software/httpbb@master] feat: add json payload capability

https://gerrit.wikimedia.org/r/884920

Change 886148 had a related patch set uploaded (by RLazarus; author: RLazarus):

[operations/software/httpbb@master] Release v0.0.3.

https://gerrit.wikimedia.org/r/886148

Change 886148 merged by RLazarus:

[operations/software/httpbb@master] Release v0.0.3.

https://gerrit.wikimedia.org/r/886148

Mentioned in SAL (#wikimedia-operations) [2023-02-02T20:21:03Z] <rzl> rzl@apt1001:~$ sudo -i reprepro -C main include buster-wikimedia ${HOME}/httpbb/buster/httpbb_${VERSION?}-1_amd64.changes # T328280

Mentioned in SAL (#wikimedia-operations) [2023-02-02T20:23:03Z] <rzl> rzl@apt1001:~$ sudo -i reprepro -C main include bullseye-wikimedia /home/rzl/httpbb/bullseye/httpbb_0.0.3-1+deb11u1_amd64.changes # T328280

This is deployed! Thanks again for the patch, let me know if you need anything else.