Can an snmpget request generate an error? - networking

Is there any context in which an snmpget request with version 2c can generate a response with a non zero error status?
After playing a bit with snmp tools provided by linux Net-SNMP applications, I could not find any such situation. In particular:
if the oid is not present in the agent mib then the agent replies with a value set to noSuchObject
same if the client cannot access the object (e.g., because some view has been defined)
if the community provided by snmpget is wrong then the agent does not answer at all.
So I'm wondering whether this situation (having a positive error status in response of an snmpget request) can occur at all.

The actual GET request processing is documented in RFC 3416 section 4.2.1,
https://datatracker.ietf.org/doc/html/rfc3416#section-4.2.1
and there are a few places/cases you must get an error response.
An actual SNMP agent must implement those error responses so as to be compliant with the standard, but it might add its own logic when needed. You can find a C# agent sample here to see how it handles GET requests and sends back error responses,
https://github.com/lextudio/sharpsnmplib-samples/blob/master/Samples.Engine/Pipeline/GetMessageHandler.cs

Related

What should the HTTP Status Code of a Degraded Health Check Be?

I have a health check endpoint at /status that returns the following status codes and response bodies:
Healthy - 200 OK
Degraded - ?
Unhealthy - 503 Service Unnavailable
What should the HTTP status code be for a degraded response be? A 'degraded' check is used for checks that did succeed but are slow or unstable. What HTTP status code makes the most sense?
The most suitable HTTP status code for a "Degraded" status response from a health endpoint is nothing other than 200 OK.
I say this because I can't find any better code in the official Hypertext Transfer Protocol (HTTP) Status Code Registry maintained by IANA, pointed to by [RFC7231] HTTP/1.1: Semantics and Content. Unofficial codes should be avoided, because they only make your API more difficult to understand.
You should design your APIs so that they become easy to use. Resource names, HTTP verbs, status codes, etc. should be more or less self-explanatory, so that people who already know "the REST language" can immediately understand how to use your API without having to decipher vague names or unusual status codes. Which brings me to the next part of my answer...
Other comments on your design
The most natural way to interpret a 5xx response to any request is that the operation in question failed.
So a 503 Service Unavailable response to a GET /status request means that the status checking operation itself failed. Such a response would only be useful if we can be certain that /status is a health endoint, as pointed out in the API Health Check draft referred to in Nkosi's answer:
A health endpoint is only meaningful in the context of the component
it indicates the health of. It has no other meaning or purpose. As
such, its health is a conduit to the health of the component.
Clients SHOULD assume that the HTTP response code returned by the
health endpoint is applicable to the entire component (e.g. a larger
API or a microservice).
But with a URL path of just /status, it is not completely obvious that this really is a health endpoint. From looking at the URL, we only know that it returns information about the status of something, but we can't really be sure what that "something" is.
Since you're also telling us that yes, it is in fact a health endpoint, I must suggest that you change the name to health. I would also suggest placing it under some base path, e.g. /things/health, to make it more clear which component it indicates the health of.
If, on the other hand, /status was actually a resource of it own, i.e. something that represents the status of some other component/thing (like its name currently suggests), then 200 OK is the only reasonable status for successful invocations, even if the thing that it indicates the status of is "Unhealthy". In that case, a 5xx would mean that no status could be obtained, and details in the response payload would be assumed to be related to a failure in the /status service itself.
So be careful with how you name things and what status codes you use!
Consider returning a custom code within the 2xx Success range that is not already taken within the known/common status codes. Similar to some of the unofficial codes not supported by any standard.
For example 218 This is fine (Apache Web Server)
Used as a catch-all error condition for allowing response bodies to flow through Apache when ProxyErrorOverride is enabled. When ProxyErrorOverride is enabled in Apache, response bodies that contain a status code of 4xx or 5xx are automatically discarded by Apache in favor of a generic response or a custom response specified by the ErrorDocument directive
After doing some research I came across a draft
Health Check Response Format for HTTP APIs: draft-inadarei-api-health-check-03
Where they also made similar suggestions
In case of the “warn” status, endpoints MUST return HTTP status in the 2xx-3xx range, and additional information SHOULD be provided, utilizing optional fields of the response.
where the warn status in the draft is healthy, with some concerns, which I believe aligns closely to your desired model.
While not definitive, I believe it provides some ideas to help with the eventual design.
I would be wary of splitting hairs like this on a healthcheck on the upstream server side. The service providing the healthcheck should be lightly (and concurrently) testing all its upstream dependencies based on its own set of policies or rules - request timeouts, connection failures and so on. In reality the healthcheck either works or it doesn't and the application shouldn't really need to be keeping track of the results of the healthcheck (other than capturing metrics about what happened). IMHO a stateful healthcheck is a recipe for disaster.
I typically use the following interface for application healthchecks:
204 - No Content, everything is working within tolerences
500 - Something failed, and here's some details in the response about what went wrong
Where it gets tricky depends on your architecture. You may have a VIP or reverse proxy that is interpreting this response and deciding if a given node is healthy or not, in which case it's going to either route the request to a healthy node or return the 503 Service Unavailable. This decision is going to made on some policy basis - x healthcheck requests failed over a y time period across z upstream services.
If you use a mesh then everyone can feed data back to the service registry to keep the health state up to date and it can be based on actual service calls rather than a healthcheck.
The client is perfectly placed to make a decision based on the health of services it depends on as they can keep track of the various responses from the service. Circuit breakers are an excellent way to handle that and can do it continuously on actual requests rather than just on the healthcheck. Circuit breaker libraries (such as resilience4j) will do this for you at the cost of setting up some policies about how many failed/slow requests constitute a bad service. Service Registrys like the netflix eureka can help with the discovery and ongoing monitoring.
Assuming you are referring to the status code of a liveness/healthcheck endpoint of a service - to distinguish from 200 OK a 203 likely seems applicable and in line with:
https://datatracker.ietf.org/doc/draft-inadarei-api-health-check/
https://www.rfc-editor.org/rfc/rfc7234#section-5.5 despite being deprecated Warning: 199-header MAY carry details
align max-age with livenessProbe.periodSeconds
HTTP/1.1 203 Non-Authoritative Information
Warning: 199 - "FooBar Warning Details"
Content-Type: application/health+json
Cache-Control: max-age=10
Connection: close
{"status": "warn"}

Where do extended (decimal, e.g. 400.1, 401.4, etc.) HTTP status codes come from?

More and more I am seeing the proliferation of decimal style HTTP status codes and I can't seem to find any RFC or other IETF recommendation or even W3C drafts or whatever on this except Microsoft IIS documentation (see https://support.microsoft.com/en-us/kb/943891)
Did Microsoft create these out of thin air? Wouldn't these decimal style status codes choke a lot of network components that might be expecting a whole integer value?
Does anyone know where these decimal status codes come from?
Julian's comment above is correct.
IIS defines substatuses to help differentiate cases within the same defined status code for debugging purposes. These aren't sent on the wire in the HTTP response; as others have noted, that's an integer. They may appear in the response entity if configured (by default, only for clients running on the same host), and they're logged in the W3C log under the "sc-substatus" column.
If you're seeing decimal status codes elsewhere (the original question), you'd need to follow up with the source of them. Particularly, if you're seeing them in the HTTP message itself, that's a protocol compliance issue.
As mentioned in the docs you also linked to:
[...]
IIS 7.0, IIS 7.5, and IIS 8.0 define the following HTTP status codes that indicate a more specific cause of a 400 error:
400.1 - Invalid Destination Header.
400.2 - Invalid Depth Header.
400.3 - Invalid If Header.
[...]
So yes, IIS defines them.
And from Wikipedia, there is this gem:
[...]
The first digit of the status code specifies one of five classes of response; the bare minimum for an HTTP client is that it recognises these five classes. The phrases used are the standard examples, but any human-readable alternative can be provided.
[...]
So it's only mandatory that it starts with a 1-5.
Even if the HTTP client doesn't understand the whole status code, it can still decide what type of response it is:
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error
Update1:
As stated in RCF7231#6:
The status-code element is a three-digit integer code giving the
result of the attempt to understand and satisfy the request.
But also:
HTTP status codes are extensible. HTTP clients are not required to
understand the meaning of all registered status codes, though such
understanding is obviously desirable. However, a client MUST
understand the class of any status code, as indicated by the first
digit, and treat an unrecognized status code as being equivalent to
the x00 status code of that class, with the exception that a
recipient MUST NOT cache a response with an unrecognized status code.
For example, if an unrecognized status code of 471 is received by a
client, the client can assume that there was something wrong with its
request and treat the response as if it had received a 400 (Bad
Request) status code. The response message will usually contain a
representation that explains the status.
Update2:
Setting a 404.1 header in PHP (although the docs say it only accepts ints)
http_response_code(404.1);
results in a classic 404
So, in conclusion, I take it, clients, when the status code is unrecognized (for instance a 401.4), transform it into a generic 400 (keeping the status class - 4 and filling with 00)

Determine whether a Basic Authentication login was successful

How does an HTTP client definitively determine whether a login was successful when using Basic Authentication? I've always thought that it was simple - look at the response code:
200 = Successful
401 = Unsuccessful
This is not correct. If you read RFC 2617 it says:
If the origin server does not wish to accept the credentials sent with
a request, it SHOULD return a 401 (Unauthorized) response. The
response MUST include a WWW-Authenticate header field containing at
least one (possibly new) challenge applicable to the requested
resource.
The word SHOULD is tricky, and in fact I've seen devices that do not return a 401 on login failure. This would suggest:
WWW-Authenticate does not exist = Successful
WWW-Authenticate exists = Unsuccessful
This is also incorrect. I'm playing with a TP-LINK router that provides the following headers:
- Server : Router Webserver
- Connection : close
- Content-Type : text/html
- WWW-Authenticate : Basic realm="TP-LINK Wireless N Router WR841N"
The response code is 200.
Here we have a 200 with a WWW-Authenticate!!!!!
Given all of this, what is the DEFINITIVE way to determine whether a BA login was successful?
RFC 7235 obsoletes RFC 2617 and one of the corrections it brings is to point out that, SHOULD is to be interpreted as per RFC 2119. (This was perhaps omitted because it is pointed out in RFC 2616, which goes hand-in-hand with 2617):
SHOULD This word, or the adjective "RECOMMENDED", mean that there
may exist valid reasons in particular circumstances to ignore a
particular item, but the full implications must be understood and
carefully weighed before choosing a different course.
So, it's not just a matter of "well, you should do that, but we understand if you don't" as should means colloquially, but rather "you must do this, unless you have an extremely good reason that you can clearly state".
If a server has a very good reason for not sending a 401, it's most likely because it is sending some other error code (e.g. 404 to pretend the resource doesn't exist unless you've successfully authenticated). The wisdom of sending anything other than 401 is perhaps questionable, but the only reason to send 200 is because you want to indicate that the response is successful. Really, while the should does allow something other than 401, it really doesn't allow 200.
Including WWW-Authenticate on the other hand, definitely doesn't mean the authentication wasn't successful. It's allowed at any time, and with other schemes apart from Basic can be necessary on successful requests (to allow a nonce-count to increment, for example).
In short you've got three possible states: Success, Authentication Error, Some Other Error. The should allows for the last of those. If you get a 200 then you were successful (or well, the server is behaving wrong, but that always applies anyway).
The 200 status is what counts. That the server keeps including WWW-Authenticate simply is a bug.
And yes, I tested this, I happen to have the same router over here.

HTTP Status Code for Captcha

Sometimes (when the resource is requested too often) I'm intercepting the presentation of a (HTML) resource with a captcha. The interception doesn't produce any redirection. It happens all at the same URI.
I'm wondering now which HTTP status code would fit most for these requirements:
it should fit semantically.
Google should understand that this interception is a temporary condition which should not affect the existing resource in its index.
A web browser will display the response body with the captcha.
These are my candidates which I identified so far:
409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict.
This sounds perfect. The conflict state comes from those clients requesting the resource too often. The response also includes enough information to identify the source of conflict plus resolve it.
503 Service Unavailable
The server is currently unable to handle the request due to a temporary overloading […] of the server. The implication is that this is a temporary condition […]. If known, the length of the delay MAY be indicated in a Retry-After header.
This sounds moderately appropriate. I might even know the length of delay and provide such header. But I'm missing here the point that the user can resolve the problem. Furthermore the scope is too broad (overloaded server vs. overloaded resource).
You may want to consider status code 429, defined in https://www.rfc-editor.org/rfc/rfc6585#section-4.
For me 422 is somewhat accurate for this case:
response status code indicates that the server understands the content
type of the request entity, and the syntax of the request entity is
correct, but it was unable to process the contained instructions.
FWIW I'm using 498.
wikipedia:
Code 498 indicates an expired or otherwise invalid token.
498 Invalid Token (Esri)
Returned by ArcGIS for Server. Code 498 indicates an expired or otherwise invalid token.[74]

HTTP 400 (bad request) for logical error, not malformed request syntax

The HTTP/1.1 specification (RFC 2616) has the following to say on the meaning of status code 400, Bad Request (§10.4.1):
The request could not be understood by
the server due to malformed syntax.
The client SHOULD NOT repeat the
request without modifications.
There seems to be a general practice among a few HTTP-based APIs these days to use 400 to mean a logical rather than a syntax error with a request. My guess is that APIs are doing this to distinguish between 400 (client-induced) and 500 (server-induced). Is it acceptable or incorrect to use 400 to indicate non-syntactic errors? If it is acceptable, is there an annotated reference on RFC 2616 that provides more insight into the intended use of 400?
Examples:
Google Data Protocol, Protocol Reference, HTTP Status Codes
Status 422 (RFC 4918, Section 11.2) comes to mind:
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
As of this time, the latest draft of the HTTPbis specification, which is intended to replace and make RFC 2616 obsolete, states:
The 400 (Bad Request) status code indicates that the server cannot or
will not process the request because the received syntax is invalid,
nonsensical, or exceeds some limitation on what the server is willing
to process.
This definition, while of course still subject to change, ratifies the widely used practice of responding to logical errors with a 400.
HTTPbis will address the phrasing of 400 Bad Request so that it covers logical errors as well. So 400 will incorporate 422.
From https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-p2-semantics-18#section-7.4.1
"The server cannot or will not process the request, due to a client error (e.g., malformed syntax)"
Even though, I have been using 400 to represent logical errors also, I have to say that returning 400 is wrong in this case because of the way the spec reads. Here is why i think so, the logical error could be that a relationship with another entity was failing or not satisfied and making changes to the other entity could cause the same exact to pass later. Like trying to (completely hypothetical) add an employee as a member of a department when that employee does not exist (logical error). Adding employee as member request could fail because employee does not exist. But the same exact request could pass after the employee has been added to the system.
Just my 2 cents ... We need lawyers & judges to interpret the language in the RFC these days :)
Thank You,
Vish
It could be argued that having incorrect data in your request is a syntax error, even if your actual request at the HTTP level (request line, headers etc) is syntactically valid.
For example, if a Restful web service is documented as accepting POSTs with a custom XML Content Type of application/vnd.example.com.widget+xml, and you instead send some gibberish plain text or a binary file, it seems resasonable to treat that as a syntax error - your request body is not in the expected form.
I don't know of any official references to back this up though, as usual it seems to be down to interpreting RFC 2616.
Update: Note the revised wording in RFC 7231 §6.5.1:
The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
seems to support this argument more than the now obsoleted RFC 2616 §10.4.1 which said just:
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
On Java EE servers a 400 is returned if your URL refers to a non-existent "web -application". Is that a "syntax error"? Depends on what you mean by syntax error. I would say yes.
In English syntax rules prescribe certain relationships between parts of speech. For instance "Bob marries Mary" is syntactically correct, because it follows the pattern {Noun + Verb + Noun}. Whereas
"Bob marriage Mary" would be syntactically incorrect, {Noun + Noun + Noun}.
The syntax of a simple URLis { protocol + : + // + server + : + port }. According to this "http://www.google.com:80" is syntactically correct.
But what about "abc://www.google.com:80"? It seems to follow the exact same pattern. But really
it is a syntax error. Why? Because 'abc' is not a DEFINED protocol.
The point is that determining whether or not we have a 400 situation requires more than parsing the characters and spaces and delimiters. It must also recognize what are the valid "parts of speech".
This is difficult.
I think we should;
Return 4xx errors only when the client has the power to make a change to the request, headers or body, that will result in the request succeeding with the same intent.
Return error range codes when the expected mutation has not occured, i.e. a DELETE didn't happen or a PUT didn't change anything. However, a POST is more interesting because the spec says it should be used to either create resources at a new location, or just process a payload.
Using the example in Vish's answer, if the request intends to add employee Priya to a department Marketing but Priya wasn't found or her account is archived, then this is an application error.
The request worked fine, it got to your application rules, the client did everything properly, the ETags matched etc. etc.
Because we're using HTTP we must respond based on the effect of the request on the state of the resource. And that depends on your API design.
Perhaps you designed this.
PUT { updated members list } /marketing/members
Returning a success code would indicate that the "replacement" of the resource worked; a GET on the resource would reflect your changes, but it wouldn't.
So now you have to choose a suitable negative HTTP code, and that's the tricky part, since the codes are strongly intended for the HTTP protocol, not your application.
When I read the official HTTP codes, these two look suitable.
The 409 (Conflict) status code indicates that the request could not be completed due to a conflict with the current state of the target resource. This code is used in situations where the user might be able to resolve the conflict and resubmit the request. The server SHOULD generate a payload that includes enough information for a user to recognize the source of the conflict.
And
The 500 (Internal Server Error) status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.
Though we've traditionally considered the 500 to be like an unhandled exception :-/
I don't think its unreasonable to invent your own status code so long as its consistently applied and designed.
This design is easier to deal with.
PUT { membership add command } /accounts/groups/memberships/instructions/1739119
Then you could design your API to always succeed in creating the instruction, it returns 201 Created and a Location header and any problems with the instruction are held within that new resource.
A POST is more like that last PUT to a new location. A POST allows for any kind of server processing of a message, which opens up designs that say something like "The action successfully failed."
Probably you already wrote an API that does this, a website. You POST the payment form and it was successfully rejected because the credit card number was wrong.
With a POST, whether you return 200 or 201 along with your rejection message depends on whether a new resource was created and is available to GET at another location, or not.
With that all said, I'd be inclined to design APIs that need fewer PUTs, perhaps just updating data fields, and actions and stuff that invokes rules and processing or just have a higher chance of expected failures, can be designed to POST an instruction form.
In my case:
I am getting 400 bad request because I set content-type wrongly. I changed content type then able to get response successfully.
Before (Issue):
ClientResponse response = Client.create().resource(requestUrl).queryParam("noOfDates", String.valueOf(limit))
.header(SecurityConstants.AUTHORIZATION, formatedToken).
header("Content-Type", "\"application/json\"").get(ClientResponse.class);
After (Fixed):
ClientResponse response = Client.create().resource(requestUrl).queryParam("noOfDates", String.valueOf(limit))
.header(SecurityConstants.AUTHORIZATION, formatedToken).
header("Content-Type", "\"application/x-www-form-urlencoded\"").get(ClientResponse.class);

Resources