7

I'm attempting to interface with an API that requires XML data to be contained in the body of an HTTP DELETE request. I'm using urlfetch in AppEngine and the payload is simply ignored for DELETE requests.

After reading this article: Is an entity body allowed for an HTTP DELETE request?, I realize that the standard probably doesn't allow body content on DELETE requests and that's why urlfetch is stripping the body.

So my question is: is there some sort of work-around to append body content in app engine when urlfetch ignores the payload?

Community
  • 1
  • 1
elkelk
  • 1,692
  • 2
  • 13
  • 20

3 Answers3

6

Per the docs,

The URL fetch service supports five HTTP methods: GET, POST, HEAD, PUT and DELETE. The request can include HTTP headers, and body content for a POST or PUT request.

Given that the GAE Python runtime is heavily sandboxed, it's extremely unlikely that you'll be able to get around this restriction. I consider that to be a bug, and you should probably file a bug report here.

Jonathan Feinberg
  • 44,698
  • 7
  • 80
  • 103
  • I agree, I have starred and commented on the issue here: http://code.google.com/p/googleappengine/issues/detail?id=601&q=post%20delete&colspec=ID%20Type%20Status%20Priority%20Stars%20Owner%20Summary%20Log%20Component – elkelk Feb 08 '10 at 16:10
  • elkelk, that bug is not related to the question here. – Jonathan Feinberg Feb 09 '10 at 14:11
2

You can make DELETE request with body via sockets, sample Java code that checks HTTPRequest and does different request for DELETE with body:

public static HTTPResponse execute(HTTPRequest request) throws ExecutionException, InterruptedException {

    if (request == null) {
        throw new IllegalArgumentException("Missing request!");
    }

    if (request.getMethod() == HTTPMethod.DELETE && request.getPayload() != null && request.getPayload().length > 0) {
        URL obj = request.getURL();
        SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        try {
            HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

            HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);

            con.setRequestMethod("DELETE");
            for (HTTPHeader httpHeader : request.getHeaders()) {
                con.setRequestProperty(httpHeader.getName(), httpHeader.getValue());
            }
            con.setDoOutput(true);
            con.setDoInput(true);

            OutputStream out = con.getOutputStream();
            out.write(request.getPayload());
            out.flush();
            out.close();
            List<HTTPHeader> responseHeaders = new ArrayList<>();
            for (Map.Entry<String, List<String>> stringListEntry : con.getHeaderFields().entrySet()) {
                for (String value : stringListEntry.getValue()) {
                    responseHeaders.add(new HTTPHeader(stringListEntry.getKey(), value));
                }
            }
            return new HTTPResponse(con.getResponseCode(), StreamUtils.getBytes(con.getInputStream()), con.getURL(), responseHeaders);
        } catch (IOException e) {
            log.severe(e.getMessage());
        }
    } else {
        Future<HTTPResponse> future = URLFetchServiceFactory.getURLFetchService().fetchAsync(request);
        return future.get();
    }
    return null;
}
dincek
  • 31
  • 1
0

You can get around this using the App Engine Socket API, here is how that looks in Go:

    client := http.Client{
        Transport: &http.Transport{
            Dial: func(network, addr string) (net.Conn, error) {
                return socket.Dial(c, network, addr)
            },
        },
    }
Chris Pushbullet
  • 1,039
  • 9
  • 10