使用Jsoup调用AddExamType接口时遭遇HTTP 500错误求助
Hey there, let's break down how to fix that 500 server error you're hitting with Jsoup. A 500 status means the server ran into an unexpected issue processing your request—usually due to a mismatch between your Jsoup request and what the server expects. Let's go through the most likely fixes based on your code and stack trace.
1. Update Session Cookies After the Initial GET Request
When you fetch the form page with GET, the server might send new session cookies (like updated CSRF tokens or session IDs) that are required for the subsequent POST. Right now, you're reusing the original Common.sessionCookies instead of updating them with the cookies from the GET response. This mismatch can trigger server errors.
Fix: Add this line right after executing the GET request:
// Update session cookies with any new ones from the form page response Common.sessionCookies.putAll(addExamResponse.cookies())
2. Fix the utf8 Form Field
Your current code sets utf8 to "e2 9c 93"—this is the byte representation of the checkmark character, but most websites expect the actual character (✓) or the value pulled directly from the form. Using the wrong value can break server-side parsing.
Better Fix: Extract the utf8 value directly from the form page instead of hardcoding it:
val utf8Value = document.select("input[name=utf8]").first()?.attr("value") ?: "✓"
Then use this value in your form data instead of the hardcoded byte string.
3. Use a Realistic User-Agent String
Your current User-Agent is just "Mozilla"—many servers validate for full browser-like User-Agent strings and reject or error on overly simple ones.
Fix: Replace your User-Agent with a full, real-world string:
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36")
Use this for both the GET and POST requests.
4. Add Comprehensive Exception Handling
Your existing try-catch only catches IOException, but even though HttpStatusException is a subclass, your coroutine context might be causing uncaught exceptions. Expanding your catch blocks will prevent crashes and give better debugging info.
Fix: Add specific catches for HttpStatusException and a general Exception catch-all, plus ensure UI updates run on the main thread:
} catch (e: HttpStatusException) { Log.e(TAG, "addExam: Server Error - Code: ${e.statusCode}, URL: ${e.url}", e) runOnUiThread { progressBar.hide() Toast.makeText(this, "Server error: ${e.statusCode}", Toast.LENGTH_LONG).show() } } catch (e: IOException) { Log.e(TAG, "addExam: Network Error", e) runOnUiThread { progressBar.hide() Toast.makeText(this, "Network issue: ${e.message}", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(TAG, "addExam: Unexpected Error", e) runOnUiThread { progressBar.hide() Toast.makeText(this, "Something went wrong: ${e.message}", Toast.LENGTH_LONG).show() } }
5. Validate Form Fields Against Browser Traffic
The best way to ensure your form data matches what the server expects is to compare it to a real browser request:
- Open your target site in Chrome/Firefox, open DevTools (F12), go to the Network tab
- Perform a manual "add exam type" action
- Find the POST request to
/Exam/AddExamTypeand check:- All form fields (including hidden ones you might be missing)
- Exact field names (case-sensitive—e.g., is it
examTypeNameinstead ofExamTypeName?) - Request headers the browser sends (you can copy these into your Jsoup request if needed)
Modified Code Example
Here's your code with all the above fixes applied:
private fun addExam() { Log.d(TAG, "addExam: Starting exam type addition") try { // Fetch the form page to get tokens and update cookies val addExamResponse = Jsoup.connect(getString(R.string.addExamUrl)) .method(Connection.Method.GET) .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .cookies(Common.sessionCookies) .execute() // Update session cookies with new ones from the GET response Common.sessionCookies.putAll(addExamResponse.cookies()) val document = addExamResponse.parse() Log.d(TAG, "addExam: Retrieved form page - URL: ${addExamResponse.url()}") // Extract required tokens from the form val authToken = document.select("input[name=__RequestVerificationToken]").first()?.attr("value") ?: throw IllegalStateException("Could not find verification token") val utf8Value = document.select("input[name=utf8]").first()?.attr("value") ?: "✓" Log.d(TAG, "addExam: Verification token retrieved: $authToken") // Build form data with valid values val formData = HashMap<String, String>().apply { put("utf8", utf8Value) put("ExamTypeName", examType.text.toString().trim()) put("Description", examDesc.text.toString().trim()) put("__RequestVerificationToken", authToken) } // Submit the POST request val examListPage = Jsoup.connect(getString(R.string.addExamUrl)) .data(formData) .method(Connection.Method.POST) .userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36") .cookies(Common.sessionCookies) .followRedirects(true) .execute() Log.d(TAG, "addExam: POST response URL: ${examListPage.url()}") runOnUiThread { progressBar.hide() } // Handle success/redirect if (examListPage.url().toString().lowercase(Locale.ROOT).contains("teacher")) { startActivity(Intent(this, HomeActivity::class.java)) finish() } else { runOnUiThread { Toast.makeText(this, "Failed to add exam type. Please check your input.", Toast.LENGTH_LONG).show() } } } catch (e: HttpStatusException) { Log.e(TAG, "addExam: Server Error - Code: ${e.statusCode}, URL: ${e.url}", e) runOnUiThread { progressBar.hide() Toast.makeText(this, "Server error: ${e.statusCode}", Toast.LENGTH_LONG).show() } } catch (e: IOException) { Log.e(TAG, "addExam: Network Error", e) runOnUiThread { progressBar.hide() Toast.makeText(this, "Network issue: ${e.message}", Toast.LENGTH_LONG).show() } } catch (e: Exception) { Log.e(TAG, "addExam: Unexpected Error", e) runOnUiThread { progressBar.hide() Toast.makeText(this, "Something went wrong: ${e.message}", Toast.LENGTH_LONG).show() } } }
Give these changes a try—most likely the cookie update or utf8 field fix will resolve the 500 error. If not, comparing your request to the browser's DevTools traffic will help spot any remaining mismatches.
内容的提问来源于stack exchange,提问作者hagar Mohamad

