HTTP 200 vs 400 from stations api

30 views
Skip to first unread message

bell...@gmail.com

unread,
Feb 19, 2024, 2:00:22 PMFeb 19
to weewx-development
I was in the process of updating restx.py to log the returned error message. If you want the stations api to return a 400, you could do something like this.

def test_post():
    url = 'http://localhost:5000/api/v2/stations/'

    body = {
        'station_url': 'example.com',
        }
    json_body = json.dumps(body)

    request = urllib.request.Request(url)
    request.add_header('Content-Type', 'application/json')

    try:
        response = urllib.request.urlopen(request, data=json_body.encode('utf-8'))
    except urllib.error.HTTPError as http_error:
        print(http_error)
        raw_data = http_error.read()
        print(raw_data)
        error_msg = raw_data.decode()
        print(error_msg)

I’m still trying to understand any edge cases/nuances, so the 200 is probably a bit ‘safer’.
rich

Tom Keffer

unread,
Feb 19, 2024, 2:21:32 PMFeb 19
to bell...@gmail.com, weewx-development
The problem is that urllib.request.urlopen() raises an exception if it gets an HTTP error code 400. That makes the response body totally unavailable.

I studied the HTTP error codes and decided that code 200 means that the HTTP transmission was successful. It does not necessarily mean that the application-level transaction was successful, i.e., the resource (in this case, a station registration) was created. So, a 200 code can be sent back even if the registration failed.

By contrast, 400 means that the client malformed the request badly enough that the server is unable to process it. Presumably, at all. 

So, I switched from 400 to 200 so that we can send some details to the client on why a registration could not be processed.

But, the documentation I read was never crystal clear on what to do when a client passed on invalid data.

Caveat: I am not an expert on this! Everything above comes from an hour or two of research on the topic --- the sum total of my expertise!

Thanks for taking a look at this, Rich!

-tk








--
You received this message because you are subscribed to the Google Groups "weewx-development" group.
To unsubscribe from this group and stop receiving emails from it, send an email to weewx-developm...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/weewx-development/45b3404d-7d3a-4e64-82bc-8cf97ff16959n%40googlegroups.com.

bell...@gmail.com

unread,
Feb 19, 2024, 2:33:43 PMFeb 19
to weewx-development
Oh the arguments/debates we had on what response code to use. It is a grey area…
My example code does read the response body on that exception. It appears you can either use the read() method on the exception or the fp attribute.
From https://docs.python.org/3/library/urllib.error.html#module-urllib.error

exception urllib.error.HTTPError(urlcodemsghdrsfp)

Though being an exception (a subclass of URLError), an HTTPError can also function as a non-exceptional file-like return value (the same thing that urlopen() returns). This is useful when handling exotic HTTP errors, such as requests for authentication.

You have something working, its not worth changing. 

rich

Ps. Flask looks pretty cool. Got the stations api running in dev mode in minutes.

bell...@gmail.com

unread,
Feb 19, 2024, 2:37:18 PMFeb 19
to weewx-development

Mumble, grumble… fp seems to added in python 3.12. Or at least that is the place it is documented.
If you wanted to pursue, I could test on other versions.
But what you ain’t broke….

Tom Keffer

unread,
Feb 19, 2024, 2:58:26 PMFeb 19
to bell...@gmail.com, weewx-development
I'm happy with what we have because it also works on older versions of WeeWX. If we start probing the exception, that would only work on new code.

bell...@gmail.com

unread,
Feb 19, 2024, 4:19:06 PMFeb 19
to weewx-development
Makes sense.

bell...@gmail.com

unread,
Feb 19, 2024, 4:21:19 PMFeb 19
to weewx-development
FYI, it all seems to work with python 3.6 - in case some stumbles onto this thread and is extending the class to interact with a service that does return a 400.
Reply all
Reply to author
Forward
0 new messages