core: Handle HTTP Post requests
authorZeeshan Ali (Khattak) <zeeshanak@gnome.org>
Thu, 28 Jan 2010 21:46:24 +0000 (23:46 +0200)
committerZeeshan Ali (Khattak) <zeeshanak@gnome.org>
Wed, 3 Feb 2010 13:38:49 +0000 (15:38 +0200)
src/rygel/Makefile.am
src/rygel/rygel-http-post.vala [new file with mode: 0644]
src/rygel/rygel-http-server.vala

index 50caa70..361d1f9 100644 (file)
@@ -56,6 +56,7 @@ VAPI_SOURCE_FILES = rygel-configuration.vala \
                    rygel-http-request.vala \
                    rygel-http-get-handler.vala \
                    rygel-http-get.vala \
+                   rygel-http-post.vala \
                    rygel-http-identity-handler.vala \
                    rygel-http-transcode-handler.vala \
                    rygel-http-seek.vala \
diff --git a/src/rygel/rygel-http-post.vala b/src/rygel/rygel-http-post.vala
new file mode 100644 (file)
index 0000000..7864db3
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2008-2010 Nokia Corporation.
+ * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
+ *                               <zeeshan.ali@nokia.com>
+ *         Jorn Baayen <jorn.baayen@gmail.com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using Soup;
+
+/**
+ * Responsible for handling HTTP POST client requests.
+ */
+internal class Rygel.HTTPPost : HTTPRequest {
+    SourceFunc handle_continue;
+
+    File file;
+    OutputStream stream;
+
+    public HTTPPost (HTTPServer   http_server,
+                     Soup.Server  server,
+                     Soup.Message msg) {
+        base (http_server, server, msg, null);
+    }
+
+    protected override async void handle () {
+        this.msg.got_chunk.connect (this.on_got_chunk);
+        this.msg.got_body.connect (this.on_got_body);
+
+        this.server.pause_message (this.msg);
+        yield base.handle ();
+
+        try {
+            this.file = yield this.item.get_writable (this.cancellable);
+            if (this.file == null) {
+                throw new HTTPRequestError.BAD_REQUEST (
+                                        "No writable URI for %s available",
+                                        this.item.id);
+            }
+
+            this.stream = yield this.file.replace_async (
+                                        null,
+                                        false,
+                                        FileCreateFlags.REPLACE_DESTINATION,
+                                        Priority.LOW,
+                                        this.cancellable);
+        } catch (Error error) {
+            this.server.unpause_message (this.msg);
+            this.handle_error (error);
+
+            return;
+        }
+
+        this.server.unpause_message (this.msg);
+        this.handle_continue = this.handle.callback;
+
+        yield;
+    }
+
+    private void on_got_body (Message msg) {
+        if (this.msg == msg) {
+            this.end (KnownStatusCode.OK);
+
+            this.handle_continue ();
+        }
+    }
+
+    private void on_got_chunk (Message msg, Buffer chunk) {
+
+        this.write_chunk.begin (chunk);
+    }
+
+    private async void write_chunk (Buffer chunk) {
+        try {
+            this.stream.write (chunk.data, chunk.length, this.cancellable);
+        } catch (Error error) {
+            this.handle_error (error);
+            this.handle_continue ();
+        }
+    }
+}
+
index a0cef18..a8eeba6 100644 (file)
@@ -51,6 +51,7 @@ internal class Rygel.HTTPServer : Rygel.TranscodeManager, Rygel.StateMachine {
     public async void run () {
         context.server.add_handler (this.path_root, server_handler);
         context.server.request_aborted.connect (this.on_request_aborted);
+        context.server.request_started.connect (this.on_request_started);
 
         if (this.cancellable != null) {
             this.cancellable.cancelled += this.on_cancelled;
@@ -191,5 +192,25 @@ internal class Rygel.HTTPServer : Rygel.TranscodeManager, Rygel.StateMachine {
             }
         }
     }
+
+    private void on_request_started (Soup.Server        server,
+                                     Soup.Message       message,
+                                     Soup.ClientContext client) {
+        message.got_headers.connect (this.on_got_headers);
+    }
+
+    private void on_got_headers (Soup.Message msg) {
+        if (msg.method == "POST" &&
+            msg.uri.path.has_prefix (this.path_root)) {
+            debug ("HTTP POST request for URI '%s'",
+                   msg.get_uri ().to_string (false));
+            var request = new HTTPPost (this, this.context.server, msg);
+
+            request.completed += this.on_request_completed;
+            this.requests.add (request);
+
+            request.run.begin ();
+        }
+    }
 }