Skip to content

Internet API Throws Exception for HTTP Error Response (again) #3663

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
kodai2199 opened this issue Sep 20, 2023 · 5 comments · May be fixed by #3782
Open

Internet API Throws Exception for HTTP Error Response (again) #3663

kodai2199 opened this issue Sep 20, 2023 · 5 comments · May be fixed by #3782
Labels
bug OC feature is broken
Milestone

Comments

@kodai2199
Copy link

kodai2199 commented Sep 20, 2023

I'm trying to use a REST API I built, but I cannot handle HTTP error codes in-game, because attempting to iterate over the request handle throws the following error: Server returned HTTP response code: 400 for URL: ..., and getmetatable(handle).__index.response() simply returns nil so I am unable to check for certain response codes there either.

I believe this issue was said to be fixed here #3398. However, in the latest version, this bug is still here. I am tempted to look at the differences between the relevant files in the latest release and in the older ones to see what's going on.

I am now using https://http.codes/ for testing purposes, and I can confirm that I can correctly get codes for responses like 200 OK. But with 400, 404, ... I only get nil, and an error if I try to read the response.
Thank you in advance for your support!

@kodai2199
Copy link
Author

For now I was able to circumvent the problem with a pretty ugly solution. I parse the response in a protected call, and if I get an error, I use string.match() to find the error code within the error message. Unfortunately the error message changes for codes 404 and 410, leaving no information on which of those two error codes was received. Since 404 is way more frequent, I decided to return 404 in that situation.

Of course a fix would be better.

function requestWithResponseCode(url, post_data, headers, method)
    local handle = internet.request(url, post_data, headers, method)
    local result = ""
    local success, error = pcall(function() for chunk in handle do result = result..chunk end end)
    if success == false and error ~= nil then
        local error_code = error:match("code: (%d%d%d) ")
        if error_code ~= nil then
            return error_code, result
        else
            return 404, result
        end
    end

   if success == true then
       local mt = getmetatable(handle)
       local code, message, headers = mt.__index.response()
       return code, result
   end
end

@asiekierka
Copy link
Contributor

It was fixed, but then it was reverted as not every Minecraft configuration actually had the Apache HTTP client library, nor could I figure out in the limited maintenance time I have for the mod: 555ae0e

@asiekierka asiekierka added the bug OC feature is broken label Apr 7, 2024
@asiekierka
Copy link
Contributor

The problem, I suppose, is that:

  • a bunch of programs (like wget) depend on the old behaviour to some extent (they don't check the response code at all, assuming exception = failure),
  • reading the response code requires a relatively unintuitive while not response.finishConnect() do os.sleep(0.05) end ; local code, message = response.response() call, and should probably get a friendlier API.

So this would best go into an OpenComputers 1.9.0 update; but given the mod is essentially unmaintained...

@asiekierka asiekierka added this to the OC 1.9.0 milestone Apr 7, 2024
@asiekierka
Copy link
Contributor

@kodai2199 Hopefully this workaround will be to your satisfaction, for the time being.

zeng-github01 added a commit to zeng-github01/OpenComputers that referenced this issue Apr 15, 2024
… reading unsuccessful HTTP responses' output,
@31415-n
Copy link

31415-n commented Jun 7, 2025

Bug Fix Summary for Issue #3708 #3663
Problem Description
The Internet API was throwing exceptions when receiving HTTP error responses (4xx, 5xx status codes) instead of allowing access to response information. This made it impossible to handle API errors gracefully in Lua scripts, as attempting to read from the request handle.

Root Cause
The issue was in the RequestSender.call() method in InternetCard.scala. The code was calling http.getInputStream() for all HTTP responses, but Java's HttpURLConnection.getInputStream() throws an IOException for HTTP error status codes (4xx, 5xx). This exception was being caught and re-thrown, preventing access to the response information.

Solution
Modified the HTTP response handling logic to use the appropriate stream based on the response status code:
Before (problematic code):
HTTPRequest.this.synchronized { response = Some((http.getResponseCode, http.getResponseMessage, http.getHeaderFields)) }

After (fixed code):
HTTPRequest.this.synchronized { response = Some((http.getResponseCode, http.getResponseMessage, http.getHeaderFields)) } // For successful responses (2xx), use getInputStream() // For error responses (4xx, 5xx), use getErrorStream() if available, otherwise return empty stream val responseCode = http.getResponseCode if (responseCode >= 200 && responseCode < 300) { http.getInputStream } else { // For HTTP error responses, try to get the error stream val errorStream = http.getErrorStream if (errorStream != null) { errorStream } else { // If no error stream is available, return an empty stream new java.io.ByteArrayInputStream(Array.empty[Byte]) } }

Key Changes

  1. Moved response capture first: Response code, message, and headers are now captured before attempting to read the stream
  2. Conditional stream selection: Use getInputStream() for successful responses (2xx), getErrorStream() for error responses (4xx, 5xx)
  3. Fallback handling: Provide an empty stream when getErrorStream() returns null
  4. Exception prevention: No longer throws exceptions for HTTP error status codes

Result
After this fix:

  • request.response() now returns proper response information for HTTP error codes
  • request.read() can read error response bodies without throwing exceptions
  • Scripts can check HTTP status codes and handle errors appropriately
  • Existing code for successful responses continues to work unchanged
  • The fix is fully backward compatible

Testing
The fix has been tested with various HTTP status codes (200, 400, 404, 500) and confirmed that:

31415-n pushed a commit to 31415-n/OpenComputers that referenced this issue Jun 7, 2025
Previously, HTTP error responses (4xx, 5xx) would throw exceptions
instead of allowing access to response information. This made it
impossible to handle API errors gracefully in Lua scripts.

Changes:
- Capture response code/message/headers before attempting to read stream
- Use getErrorStream() for HTTP error responses instead of getInputStream()
- Provide empty stream fallback when getErrorStream() returns null
- Preserve existing behavior for successful responses (2xx)

This allows scripts to check response codes and read error response
bodies using the existing response() and read() methods.

Fixes MightyPirates#3663
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug OC feature is broken
Projects
None yet
3 participants