{"record":{"id":"69f357e926649855","repo":"languagetool-org/languagetool","slug":"url-needs-to-be-called-with-get","errorCode":null,"errorMessage":"<url> needs to be called with GET","messagePattern":"<url> needs to be called with GET","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"languagetool-server/src/main/java/org/languagetool/server/ApiV2.java","lineNumber":402,"sourceCode":"      if (userInfo != null) {\n        if (format.equals(\"minimal\")) {\n          StringWriter sw = new StringWriter();\n          new ObjectMapper().writeValue(sw, userInfo);\n          sendJson(httpExchange, sw);\n        } else {\n          StringWriter sw = new StringWriter();\n          new ObjectMapper().writeValue(sw, DatabaseAccess.getInstance().getExtendedUserInfo(user));\n          sendJson(httpExchange, sw);\n        }\n      } else {\n        throw new IllegalStateException(\"Could not fetch user information\");\n      }\n    }\n  }\n\n  private void ensureGetMethod(HttpExchange httpExchange, String url) {\n    if (!httpExchange.getRequestMethod().equalsIgnoreCase(\"get\")) {\n      throw new BadRequestException(url + \" needs to be called with GET\");\n    }\n  }\n  \n  private void ensurePostMethod(HttpExchange httpExchange, String url) {\n    if (!httpExchange.getRequestMethod().equalsIgnoreCase(\"post\")) {\n      throw new BadRequestException(url + \" needs to be called with POST\");\n    }\n  }\n\n  @NotNull\n  private UserLimits getUserLimits(Map<String, String> parameters, HTTPServerConfig config) {\n    UserLimits limits = ServerTools.getUserLimits(parameters, config);\n    if (limits.getPremiumUid() == null) {\n      throw new BadRequestException(\"This end point needs a user id\");\n    }\n    return limits;\n  }\n","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-server/src/main/java/org/languagetool/server/ApiV2.java#L384-L420","documentation":"ensureGetMethod guards endpoints that only support GET (e.g. /words, /ruleExamples, /users/me). If the request method is not GET (case-insensitive), it throws a BadRequestException of the form '<url> needs to be called with GET'.","triggerScenarios":"POST to /v2/words, /v2/ruleExamples or /v2/users/me; PUT/DELETE calls generated by a generic REST client; follow-up redirects that change the method.","commonSituations":"Clients assuming all endpoints accept POST like /v2/check; REST frameworks auto-routing reads as POST with an _method override that the server ignores.","solutions":["Send the request with the GET method instead of POST/PUT/DELETE.","Move any parameters from the request body into the URL query string.","Check redirect handling — some clients convert GET to POST on 307/308; re-issue as GET."],"exampleFix":"// before\ncurl -X POST 'https://server/v2/ruleExamples?lang=en-US&ruleId=X'\n// after\ncurl 'https://server/v2/ruleExamples?lang=en-US&ruleId=X'","handlingStrategy":"validation","validationCode":"if (method.toUpperCase() !== 'GET') throw new Error(`${url} must be called with GET; move params into the query string`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use GET for /v2/words, /v2/ruleExamples, /v2/users/me.","Place all parameters in the URL query string, not the body.","Check redirect behavior so clients don't change the method mid-flight."],"tags":["http","rest-api","method-not-allowed","languagetool"],"backgroundTag":"unsupported-operation","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}