Author: cmpilato
Date: Mon May 17 18:09:28 2010
New Revision: 945280

URL: http://svn.apache.org/viewvc?rev=945280&view=rev
Log:
Expand the HTTPv2 POST handler for general purpose use, similar to the
read-only REPORT functionality offered elsewhere.

* build.conf
  (mod_dav_svn): Add posts/*.c to sources.

* subversion/mod_dav_svn/posts,
* subversion/mod_dav_svn/posts/create-transaction.c,
* subversion/mod_dav_svn/dav_svn.h
  (dav_svn__create_transaction_post): New POST handler function.  And
    file to hold it.  And folder to hold *that*.

* subversion/mod_dav_svn/repos.c
  (dav_svn__method_post): Expand this function for use as a more
    general-purpose dispatcher of various custom HTTPv2 POST requests.
  
* subversion/libsvn_ra_serf/commit.c
  Generate more fully formed create-transaction POST requests now.

Added:
    subversion/trunk/subversion/mod_dav_svn/posts/   (with props)
    subversion/trunk/subversion/mod_dav_svn/posts/create-transaction.c   (with 
props)
Modified:
    subversion/trunk/build.conf
    subversion/trunk/subversion/libsvn_ra_serf/commit.c
    subversion/trunk/subversion/mod_dav_svn/dav_svn.h
    subversion/trunk/subversion/mod_dav_svn/repos.c

Modified: subversion/trunk/build.conf
URL: 
http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=945280&r1=945279&r2=945280&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Mon May 17 18:09:28 2010
@@ -337,7 +337,7 @@ msvc-export = svn_wc.h private\svn_wc_pr
 description = Subversion plug-in for the Apache DAV module
 type = apache-mod
 path = subversion/mod_dav_svn
-sources = *.c reports/*.c
+sources = *.c reports/*.c posts/*.c
 libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr
 nonlibs = apr aprutil
 install = apache-mod

Modified: subversion/trunk/subversion/libsvn_ra_serf/commit.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_ra_serf/commit.c?rev=945280&r1=945279&r2=945280&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/trunk/subversion/libsvn_ra_serf/commit.c Mon May 17 18:09:28 2010
@@ -1046,6 +1046,24 @@ post_headers_iterator_callback(void *bat
 }
 
 
+static serf_bucket_t *
+create_post_body(void *baton,
+                 serf_bucket_alloc_t *alloc,
+                 apr_pool_t *pool)
+{
+  serf_bucket_t *body_bkt;
+
+  body_bkt = serf_bucket_aggregate_create(alloc);
+
+  svn_ra_serf__add_xml_header_buckets(body_bkt, alloc);
+  svn_ra_serf__add_open_tag_buckets(body_bkt, alloc, "S:create-transaction",
+                                    "xmlns:S", SVN_XML_NAMESPACE, NULL);
+  svn_ra_serf__add_close_tag_buckets(body_bkt, alloc, "S:create-transaction");
+
+  return body_bkt;
+}
+
+
 /* A custom serf_response_handler_t which is mostly a wrapper around
    svn_ra_serf__handle_status_only -- it just notices POST response
    headers, too.
@@ -1106,6 +1124,10 @@ open_root(void *edit_baton,
       handler->response_handler = post_response_handler;
       handler->response_baton = prc;
 
+      handler->body_delegate = create_post_body;
+      handler->body_delegate_baton = post_ctx;
+      handler->body_type = "text/xml";
+
       svn_ra_serf__request_create(handler);
 
       SVN_ERR(svn_ra_serf__context_run_wait(&post_ctx->done, ctx->session,

Modified: subversion/trunk/subversion/mod_dav_svn/dav_svn.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/dav_svn.h?rev=945280&r1=945279&r2=945280&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/dav_svn.h (original)
+++ subversion/trunk/subversion/mod_dav_svn/dav_svn.h Mon May 17 18:09:28 2010
@@ -594,7 +594,7 @@ static const dav_report_elem dav_svn__re
 };
 
 
-/* The various report handlers, defined in reports/, and used by version.c.  */
+/* The various REPORT handlers, defined in reports/, and used by version.c.  */
 dav_error *
 dav_svn__update_report(const dav_resource *resource,
                        const apr_xml_doc *doc,
@@ -637,6 +637,14 @@ dav_svn__get_deleted_rev_report(const da
                                 const apr_xml_doc *doc,
                                 ap_filter_t *output);
 
+/* The various POST handlers, defined in posts/, and used by
+   dav_svn__method_post(). */
+int
+dav_svn__create_transaction_post(const dav_resource *resource,
+                                 const apr_xml_doc *doc,
+                                 ap_filter_t *output);
+
+
 /*** authz.c ***/
 
 /* A baton needed by dav_svn__authz_read_func(). */

Propchange: subversion/trunk/subversion/mod_dav_svn/posts/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon May 17 18:09:28 2010
@@ -0,0 +1 @@
+.libs

Added: subversion/trunk/subversion/mod_dav_svn/posts/create-transaction.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/posts/create-transaction.c?rev=945280&view=auto
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/posts/create-transaction.c (added)
+++ subversion/trunk/subversion/mod_dav_svn/posts/create-transaction.c Mon May 
17 18:09:28 2010
@@ -0,0 +1,71 @@
+/*
+ * create-transaction.c: mod_dav_svn POST handler for creating a new
+ *                       commit transaction
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+#include <apr_tables.h>
+
+#include <httpd.h>
+#include <mod_dav.h>
+
+#include "svn_dav.h"
+#include "../dav_svn.h"
+
+
+/* Respond to a S:dated-rev-report request. */
+int
+dav_svn__create_transaction_post(const dav_resource *resource,
+                                 const apr_xml_doc *doc,
+                                 ap_filter_t *output)
+{
+  request_rec *r = resource->info->r;
+  apr_bucket_brigade *bb;
+  apr_status_t apr_err;
+  dav_error *derr = NULL;
+  const char *txn_name;
+
+  /* Create a Subversion repository transaction based on HEAD, and
+     return the new transaction's name in a custom "201 Created"
+     response header.  */
+  derr = dav_svn__create_txn(resource->info->repos, &txn_name, resource->pool);
+  if (derr)
+    return dav_svn__error_response_tag(r, derr);
+
+  /* We'll set this header only because some early 1.7-dev client
+     expect it. */
+  apr_table_set(r->headers_out, SVN_DAV_TXN_NAME_HEADER, txn_name);
+  r->status = HTTP_CREATED;
+
+  bb = apr_brigade_create(resource->pool, output->c->bucket_alloc);
+  apr_err = ap_fprintf(output, bb,
+                       DAV_XML_HEADER DEBUG_CR
+                       "<S:transaction xmlns:S=\"" SVN_XML_NAMESPACE "\""
+                       ">%ld</S:transaction",
+                       apr_xml_quote_string(resource->pool, txn_name, 0));
+  if (apr_err)
+    derr = dav_svn__convert_err(svn_error_create(apr_err, 0, NULL),
+                                HTTP_INTERNAL_SERVER_ERROR,
+                                "Error writing POST response.",
+                                resource->pool);
+      
+  return dav_svn__final_flush_or_error(r, bb, output, derr, resource->pool);
+}

Propchange: subversion/trunk/subversion/mod_dav_svn/posts/create-transaction.c
------------------------------------------------------------------------------
    svn:mime-type = text/x-csrc

Modified: subversion/trunk/subversion/mod_dav_svn/repos.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/mod_dav_svn/repos.c?rev=945280&r1=945279&r2=945280&view=diff
==============================================================================
--- subversion/trunk/subversion/mod_dav_svn/repos.c (original)
+++ subversion/trunk/subversion/mod_dav_svn/repos.c Mon May 17 18:09:28 2010
@@ -4270,21 +4270,6 @@ dav_svn__create_version_resource(dav_res
    many different kinds of operations as specified by the body of the
    POST request itself.
 
-   ### TODO: Define what the format of those POST bodies might be.  If
-   ### XML, we have access to Apache's streamy XML parsing code, but
-   ### ... it's XML.  Meh.  If skels, we get skels!  But we need to
-   ### write our own streamy skel parsing routine around a brigade
-   ### read loop.  Ewww...
-   ###
-   ### Today we only support transaction creation requests, but we
-   ### could conceivable support the likes of a multi-path lock
-   ### and/or unlock request, or some other thing for which stock
-   ### WebDAV doesn't work or doesn't work well enough.
-   ###
-   ### Fortunately, today we don't use the POST body at all, and we'll
-   ### be able to get away with not defining the body format in the
-   ### future thanks to the following:
-
    As a special consideration, an empty POST body is interpreted as a
    simple request to create a new commit transaction based on the HEAD
    revision.  The new transaction name will be returned via a custom
@@ -4295,27 +4280,89 @@ int dav_svn__method_post(request_rec *r)
   dav_resource *resource;
   dav_error *derr;
   const char *txn_name;
+  const char *content_type;
 
-  derr = get_resource(r, dav_svn__get_root_dir(r),
-                      "ignored", 0, &resource);
-  if (derr != NULL)
-    return derr->status;
-
-  if (resource->info->restype != DAV_SVN_RESTYPE_ME)
-    return HTTP_BAD_REQUEST;
+  content_type = apr_table_get(r->headers_in, "Content-Type");
 
-  /* Create a Subversion repository transaction based on HEAD. */
-  derr = dav_svn__create_txn(resource->info->repos, &txn_name, resource->pool);
-  if (derr)
-    return dav_svn__error_response_tag(r, derr);
-
-  /* Build a "201 Created" response with header that tells the client
-     our new transaction's name. */
-  apr_table_set(resource->info->r->headers_out, SVN_DAV_TXN_NAME_HEADER,
-                txn_name);
-  r->status = HTTP_CREATED;
-
-  return OK;
+  derr = get_resource(r, dav_svn__get_root_dir(r), "ignored", 0, &resource);
+  if (derr != NULL)
+    {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                    "Error fetching resource for POST request.");
+      return derr->status;
+    }
+
+  if (resource->info->restype == DAV_SVN_RESTYPE_ME)
+    {
+      /* XML request type.  Parse the document, and dispatch to
+         working functions based on the outermost tag. */
+      if (content_type && (strcmp(content_type, "text/xml") == 0))
+        {
+          int result;
+          apr_xml_doc *doc;
+
+          /* Parse the XML. */
+          if ((result = ap_xml_parse_input(r, &doc)) != OK)
+            return result;
+
+          /* Uh-ohs.  No XML document!  */
+          if (! doc)
+            {
+              ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                            "XML POST request body must specify a report.");
+              return HTTP_BAD_REQUEST;
+            }
+
+          /* Okey dokey.  We've got an XML document.  Let's hand off
+             to helper functions to do the dirty work.  */
+          if (doc->root->ns == dav_svn__find_ns(doc->namespaces,
+                                                SVN_XML_NAMESPACE))
+            {
+              if (strcmp(doc->root->name, "create-transaction") == 0)
+                {
+                  return dav_svn__create_transaction_post(resource, doc,
+                                                          r->output_filters);
+                }
+              /*
+              else if (strcmp(doc->root->name, "lock-paths") == 0)
+                {
+                  return dav_svn__lock_paths_post(resource, doc,
+                                                  r->output_filters);
+                }
+              else if (strcmp(doc->root->name, "lock-paths") == 0)
+                {
+                  return dav_svn__unlock_paths_post(resource, doc,
+                                                    r->output_filters);
+                }
+              */
+            }
+
+          /* Hrm.  Nobody handled the request.  Must be something we
+             don't understand. */
+          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "Unsupported POST operation type.");
+          return HTTP_NOT_IMPLEMENTED;
+        }
+      else if (content_type)
+        {
+          ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                        "Unsupported POST content-type.");
+          return HTTP_BAD_REQUEST;
+        }
+
+      /* ### Some 1.7-dev clients expect an empty POST request to
+         ### create a new transaction, so we'll support that as a sort
+         ### of default operation for POST against the "me resource".  */
+      return dav_svn__create_transaction_post(resource, NULL,
+                                              r->output_filters);
+    }
+  else
+    {
+      ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                   "Invalid POST target resource.");
+      return HTTP_BAD_REQUEST;
+    }
+  /* ### shouldn't get here ### */
 }
 
 


Reply via email to