You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Emmanuel Dreyfus <ma...@netbsd.org> on 2022/12/02 08:53:07 UTC

MS-WDV (was Re: Help with buckets)

Hello

I made some progress with the combined GET+PROPFIND specified
by MS-WDV (for a summary, see
https://lists.apache.org/thread/57s1vvl6k9qpdv5ym7mtcl29bd933w7k )

Attached is the diff against trunk, form comments.



-- 
Emmanuel Dreyfus
manu@netbsd.org

Re: MS-WDV (was Re: Help with buckets)

Posted by Emmanuel Dreyfus <ma...@netbsd.org>.
On Fri, Dec 02, 2022 at 03:17:05PM +0000, Joe Orton wrote:
> I think this might need to do something more complex, maybe running the 
> PROPFIND in a subrequest properly and capturing (buffering) the output 
> in a custom filter, rather than using the mod_dav internal API directly. 
> Have you tried using ap_sub_req_method_uri()? Not sure this has been 
> tried before with mod_dav so might well be something I'm missing.

I did it the way you suggested. The patch gets huge, I just send the
reelvant bits. Does it looks good to you?

In register_hooks() I have
    ap_register_output_filter("DAV_MSEXT_OUT", dav_msext_output, NULL,
                              AP_FTYPE_RESOURCE);
Then:

static apr_status_t dav_msext_output(ap_filter_t *f,
                                     apr_bucket_brigade *bb)
{
    apr_bucket_brigade *bbsub = f->ctx;
    apr_bucket *b;

    b = APR_BRIGADE_FIRST(bb);
    while (b != APR_BRIGADE_SENTINEL(bb)) {
        apr_bucket *nb;
        if (APR_BUCKET_IS_EOS(b))
            break;

        nb = APR_BUCKET_NEXT(b);
        APR_BUCKET_REMOVE(b);
        APR_BRIGADE_INSERT_TAIL(bbsub, b);
        b = nb;
    }

    return ap_pass_brigade(f->next, bb);
}

static void dav_msdavext_combined_propfind(request_rec *r)
{
    apr_bucket_brigade *bbsub;
    apr_bucket_brigade *bb;
    ap_filter_t *f;
    apr_bucket *b;
    request_rec *rr = NULL;
    apr_off_t length;

    bbsub = apr_brigade_create(r->pool, r->output_filters->c->bucket_alloc);

    rr = ap_sub_req_method_uri("PROPFIND", r->uri, r, r->output_filters);
    if (!rr || rr->status != HTTP_OK)
        goto out;
    
    f = ap_add_output_filter("DAV_MSEXT_OUT", bbsub, rr, rr->connection);
    if (!f)
        goto out;

    if (ap_run_sub_req(rr) != OK)
        goto out;

    ap_remove_output_filter(f);

    if (apr_brigade_length(bbsub, 1, &length) != APR_SUCCESS)
        goto out;

    bb = apr_brigade_create(r->pool,r->output_filters->c->bucket_alloc);

    apr_brigade_printf(bb, NULL, NULL, 
                       "%016" APR_UINT64_T_HEX_FMT, length);

    APR_BRIGADE_CONCAT(bb, bbsub);

    ap_destroy_sub_req(rr);
    rr = NULL;

    rr = ap_sub_req_lookup_uri(r->uri, r, r->output_filters);
    if (!rr || rr->status != HTTP_OK || rr->filename == NULL ||
        rr->finfo.filetype != APR_REG)
        goto out;

    apr_brigade_printf(bb, NULL, NULL, 
                       "%016" APR_UINT64_T_HEX_FMT, rr->finfo.size);

    ap_set_content_type(r, "multipart/MSDAVEXTPrefixEncoded");

    ap_pass_brigade(r->output_filters, bb);

    /* plain GET rocessing happens afterward */
out:
    if (rr)
        ap_destroy_sub_req(rr);

    return;
}


-- 
Emmanuel Dreyfus
manu@netbsd.org

Re: MS-WDV (was Re: Help with buckets)

Posted by Ruediger Pluem <rp...@apache.org>.

On 12/2/22 4:42 PM, Emmanuel Dreyfus wrote:
> On Fri, Dec 02, 2022 at 03:17:05PM +0000, Joe Orton wrote:
>> I think this might need to do something more complex, maybe running the 
>> PROPFIND in a subrequest properly and capturing (buffering) the output 
>> in a custom filter, rather than using the mod_dav internal API directly. 
>> Have you tried using ap_sub_req_method_uri()? Not sure this has been 
>> tried before with mod_dav so might well be something I'm missing.
> 
> I can try that, but whatever the method is, we need to produce the
> propfind data before sending its size.
> 
> I see two unsatisfying alternatives:
> 
> 1) produce propfind data in a buffer, output the size, then the buffer
> 
> 2) produce propfind data, discarding it as it comes but coutning its size, 
> then output the size, and produce the propfind data a second time.
> 
> First approach wastes memory, second approach wastes CPU. And second approach
> needs a mechanism to ensure propfind data does not change between the two
> times it is produced. I am not sure that can be guaranteed.

I think we cannot guarantee this, which leaves us with 1.

Regards

RĂ¼diger


Re: MS-WDV (was Re: Help with buckets)

Posted by Emmanuel Dreyfus <ma...@netbsd.org>.
On Fri, Dec 02, 2022 at 03:17:05PM +0000, Joe Orton wrote:
> I think this might need to do something more complex, maybe running the 
> PROPFIND in a subrequest properly and capturing (buffering) the output 
> in a custom filter, rather than using the mod_dav internal API directly. 
> Have you tried using ap_sub_req_method_uri()? Not sure this has been 
> tried before with mod_dav so might well be something I'm missing.

I can try that, but whatever the method is, we need to produce the
propfind data before sending its size.

I see two unsatisfying alternatives:

1) produce propfind data in a buffer, output the size, then the buffer

2) produce propfind data, discarding it as it comes but coutning its size, 
then output the size, and produce the propfind data a second time.

First approach wastes memory, second approach wastes CPU. And second approach
needs a mechanism to ensure propfind data does not change between the two
times it is produced. I am not sure that can be guaranteed.

-- 
Emmanuel Dreyfus
manu@netbsd.org

Re: MS-WDV (was Re: Help with buckets)

Posted by Joe Orton <jo...@redhat.com>.
On Fri, Dec 02, 2022 at 08:53:07AM +0000, Emmanuel Dreyfus wrote:
> Hello
> 
> I made some progress with the combined GET+PROPFIND specified
> by MS-WDV (for a summary, see
> https://lists.apache.org/thread/57s1vvl6k9qpdv5ym7mtcl29bd933w7k )
> 
> Attached is the diff against trunk, form comments.

Hi Emmanuel,

That's a very weird protocol design, wow. Have you tested this with a 
long PROPFIND response? It needs to buffer the entire response in the 
output brigade to work out the length in the "multipart" prefix, but 
mod_dav will flush output brigades down the filter chain regularly 
during the multistatus response processing.

I think this might need to do something more complex, maybe running the 
PROPFIND in a subrequest properly and capturing (buffering) the output 
in a custom filter, rather than using the mod_dav internal API directly. 
Have you tried using ap_sub_req_method_uri()? Not sure this has been 
tried before with mod_dav so might well be something I'm missing.

Regards, Joe