Archived Support Site

This support site is archived. You can view the old support discussions but you cannot post new discussions.

400 Bad Request (intended)

Mikkel's Avatar

Mikkel

09 Feb, 2011 07:36 PM

Hello,

I'm trying to implement an API that relies on status codes (mostly code 200 and 400) and response JSON/XML, but I can't see the actual response for code 400, which the client needs to read.

So far I've tried with under <system.web />, as well as a few combinations under <system.webServer />, but without luck.

How do I make this work?

I don't have access to any local IIS installs to play around with at the moment, so I hope you can help me out.

Thanks,
Mikkel

  1. Support Staff 1 Posted by rune on 10 Feb, 2011 07:16 AM

    rune's Avatar

    Hi Mikkel,

    Not quite sure what you're asking here - doesn't the web server return 400 or would you like to see what it contains?

    I guess what the clients of an API would need to read would be mainly the HTTP status code itself?

    Otherwise, if you want to see the 400 response, you could perhaps make a request that will return a 400?

    Be aware though that as we're using nginx as a reverse proxy for load balancing you may get a 400 from nginx rather than IIS. But that probably shouldn't be a problem if the clients just read and rely on the status code (which would probably be a good idea if you're not issuing the 400 from you own code).

    Best regards,
    Rune

  2. 2 Posted by Mikkel Lønow on 10 Feb, 2011 08:46 AM

    Mikkel Lønow's Avatar

    Hi Rune,

    It does return the right status code (from own code, custom
    HttpHandler), I would just like to view what it contains. In the
    content I can display more details about the error (custom code and
    message).

    That's how many of the popular APIs around the web does it.

    Hopefully there's a solution to this. Otherwise I would have to rely
    on status code 200 only and then redesign my API to return objects,
    which always have an error field that the client must check. The API
    will mostly be used by mobile devices so I'm trying to keep it as
    light as possible.

    Kind regards,
    Mikkel

  3. Support Staff 3 Posted by rune on 10 Feb, 2011 11:14 AM

    rune's Avatar

    Hi Mikkel,

    Unless I've misunderstood something, I don't think this is really AppHarbor specific? So it probably falls outside of the scope of our support. That being said I'll be happy to share some immediate thoughts on how you are building your API.

    The client will see whatever you end up writing in the response. If you have a HttpContext object, the client will see what is written with for instance httpContext.Response.Write("Doesn't work"). I'm guessing you already know that :-)

    It's probably best to stick to the status codes rather than returning an object, after all that's pretty much what they are there for and as you've said, this is what others expect.

    It sounds like you want to invoke the API so you can see it in your browser? If so, you can do that by invoking the API with a request that'll return what you want to test. In that case the result should be able to do it in the same way whether you run it locally or on AppHarbor. Testing it through your browser probably isn't the best way of testing the API though.

    I guess there's really only one good answer to your question - how do I verify the behaviour of my API - which is automated tests. Pick a unit test framework you like and verify that the behaviour is what you expect it to be. Having tests along with your code also ensures that you don't break anything by accident, and you'll be confident that your API is always working the way you, and consumers of the API, would expect it to. You'll probably have to mock your HttpContext, the HttpResponse of it and the input stream (if not more).

    If you write unit tests you get the added benefit of our continous integration-like approach to deployment. We run your unit tests before deploying the code which ensures that code with unexpected behaviour won't be deployed.

    If you want I'll be happy to share some of the code I've previously used to verify behaviour in similar situations. If you want to try it out for yourself I can recomment Moq (for mocking objects) and xUnit as the test framework. You can read about supported test frameworks here: http://support.appharbor.com/kb/getting-started/running-unit-tests-...

    Best regards,
    Rune

  4. rune closed this discussion on 10 Feb, 2011 11:14 AM.

  5. Mikkel Lønow re-opened this discussion on 10 Feb, 2011 12:17 PM

  6. 4 Posted by Mikkel Lønow on 10 Feb, 2011 12:17 PM

    Mikkel Lønow's Avatar

    Hi Rune,

    Locally I get the right response (this is a Mac with Mono setup), but when I
    request the same resource deployed to AppHarbor, I only see "Bad Request".
    I'm guessing it might be your reverse proxy, as you've mentioned earlier.

    Yeah, I see everything I write with the Response object unless I alter the
    status code (to something else than 200).

    I want to invoke the API from Javascript in desktop/mobile browsers and
    native apps on mobile devices. Until I add request objects, testing through
    the browser should be sufficient.

    The reason I want to return objects is that there might be times where a
    third party consumer wants to know why a certain request failed. This is
    mostly concerning user input. Here's an example: User X wants to create a
    new album our service but X forgets to input a title. The third party API
    consumer doesn't validate input fields or unit tests their code, so a new
    album request is sent without a title. If we just respond with a 400 "Bad
    Request" X will have no clue why the request failed. Additionally, the third
    party developer will be supported with specific responses while developing.
    Other reasons could be permissions, redundancy, consumer logging etc.

    It's not the behavior of the API that I'm worried about - I'll control that
    with unit tests when I get to it :) - it's the request objects. The first
    party consumer app will be tested thoroughly, of course!

    Here's a few other APIs which relies on status codes and custom messages:

    http://apiwiki.twitter.com/w/page/22554652/HTTP-Response-Codes-and-Errors
    http://www.campaignmonitor.com/api/clients/
    http://developers.facebook.com/docs/reference/api/ (
    https://graph.facebook.com/215.dk/members?access_token=TOKEN&limit=500) -
    try altering the request and see how the error looks.

    Kind regards,
    Mikkel

  7. 5 Posted by Mikkel on 10 Feb, 2011 01:11 PM

    Mikkel's Avatar

    Hi again,

    Is proxy_intercept_errors set to on (http://wiki.nginx.org/HttpProxyModule#proxy_intercept_errors)?

    I've investigated msie_padding (http://wiki.nginx.org/NginxHttpCoreModule#msie_padding) with a response bigger than 512 bytes as well, but that didn't help.

    Kind regards,
    Mikkel

  8. Support Staff 6 Posted by rune on 10 Feb, 2011 06:16 PM

    rune's Avatar

    It's actually IIS that returns the error page, not nginx. I've checked that we haven't isn't proxy_intercept_errors on, but thanks for looking it up!

    You can reproduce the same behaviour locally by running it from IIS. In that case, to match our configuration, you will have to set the httpErrors mode to Custom in the system.webServer section like so:

    <system.webServer>
        <httpErrors errorMode="Custom">
        </httpErrors>
     </system.webServer>
    

    As far as I can tell the 400 status code is not customizable in IIS (at least version 6) http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Libr... .. Then again, there should be some way around this.

    The twitter API seems to return an 403 (at least in some cases) when there is an error in the request: http://search.twitter.com/search.json (and as far as I can tell from the documentation, only if there's not a more appropriate status code to use. I'm not sure if any of them actually return a 400? Have you seen that elsewhere?

    I know you don't have access to an IIS, but it might be a good idea to get as you'll be able to debug it on your own machine as you go. Otherwise you're of course welcome to keep pushing to us, the behaviour is the same. We sure want to help you and I'll get one of the other supporters to have a look at it and see if I've missed something.

    To try and help you develop this feature I've created a small sample application you can use if you don't want to mess around with your own repository. I've added you as a collaborator (it's called statuscodes) - if you want me to remove you again, so it isn't in your application list, let me know :-)

    Best regards,
    Rune

  9. 7 Posted by Mikkel Lønow on 10 Feb, 2011 07:13 PM

    Mikkel Lønow's Avatar

    Hey Rune,

    Okay, thanks for verifying that.

    Are you running IIS 6 or 7?

    I can't seem to override with this (gives code 500 for every request):

    <system.webServer>
    <httpErrors existingResponse="PassThrough">
    </httpErrors>
    </system.webServer>

    Is this not possible with your setup? It might be the solution I'm looking
    for (also mentioned in my initial post, but I remember it just didn't do
    anything). More info here:
    http://www.iis.net/ConfigReference/system.webServer/httpErrors

    The other links I provided should all use code 400 for custom errors (plus a
    few other codes). Try the one for Facebook for example.

    I'll try and see if I can setup IIS on an older laptop over the weekend. It
    might be useful in other scenarios, I'm sure.

    That's very cool, Rune. Thanks. I've messed around with the Web.config (the
    addition above, for instance), but for coding on that repo I need to upgrade
    my Mono version to a newer release candidate, as MVC3 isn't supported in my
    current version (although, there are ways around that).

    Thanks for taking time to help me out, I'm sure you have loads of other
    stuff to do on your startup as well.

    Kind regards,
    Mikkel

    On Thu, Feb 10, 2011 at 19:16, Rune Sørensen <
    [email blocked]> wrote:

  10. 8 Posted by Mikkel Lønow on 10 Feb, 2011 07:53 PM

    Mikkel Lønow's Avatar

    Hi again,

    Check out Security Considerations on
    http://learn.iis.net/page.aspx/267/how-to-use-http-detailed-errors-in-iis-70/-
    it might be related.

    What does the <httpErrors> section in applicationHost.config look like?

    Kind regards,
    Mikkel

  11. Support Staff 9 Posted by rune on 12 Feb, 2011 07:56 AM

    rune's Avatar

    Hi Mikkel,

    the 500 happened because the <system.webServer> element was nested inside another <system.webServer> element, so the configuration file was invalid.

    Otherwise you were on the right track - the errorMode attribute of HttpErrors needs to be set to "Detailed".

    If nothing is written to the response stream you'll then get a detailed error page. It's seems like something has to written before you'll avoid that one. I've updated the sample so it also writes something in the response - I think this should fix your problem?

    You can see how it's working by specifying a message in the querystring like so:
    http://statuscodes.apphb.com/StatusCode/show/400?message=hello

    If you remove the message from the querystring it'll fall back to the detailed error page.

    You can just pull from the AppHarbor repo if you want to see what I did :-)

    Hope this helps,
    Rune

  12. rune closed this discussion on 12 Feb, 2011 07:56 AM.

  13. Mikkel re-opened this discussion on 12 Feb, 2011 05:07 PM

  14. 10 Posted by Mikkel on 12 Feb, 2011 05:07 PM

    Mikkel's Avatar

    Ooops, you're right. How did I miss that.

    I've set existingResponse="PassThrough" for my own application and it's working as expected. I don't want to have the detailed information available to clients.

    Thanks for your help!

    Mikkel

  15. Support Staff 11 Posted by rune on 14 Feb, 2011 07:08 PM

    rune's Avatar

    Hi Mikkel,

    Sounds like a good idea not allow detailed errors in general.. Hope you'll make an awesome API :-)

    Best regards,
    Rune

  16. rune closed this discussion on 14 Feb, 2011 07:08 PM.

Discussions are closed to public comments.
If you need help with AppHarbor please start a new discussion.

Keyboard shortcuts

Generic

? Show this help
ESC Blurs the current field

Comment Form

r Focus the comment reply box
^ + ↩ Submit the comment

You can use Command ⌘ instead of Control ^ on Mac