FAQ
I've touched on this before, and posted about it on UP:
http://use.perl.org/~jk2addict/journal/35411

In a nutshell, Firefox 2.x Accept header totaly screws with the REST
controller when you use it as a base for View negotiations. If you have
a default type of text/html pointed to a View::TT, REST will see
text/xml from Firefox and try and send that instead, based on this header:

text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

What does everyone think about a config option/toggle to tell REST to
ignore the Accept header, allowing it to fall back to the default
content-type in config when no Cntent-Type header or content-type params
are specified?

-=Chris

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 187 bytes
Desc: OpenPGP digital signature
Url : http://lists.scsys.co.uk/pipermail/catalyst/attachments/20080117/2fd526cb/signature.pgp

Search Discussions

  • Jonas Alves at Jan 17, 2008 at 5:58 pm

    On Jan 17, 2008 2:32 PM, Christopher H. Laco wrote:
    I've touched on this before, and posted about it on UP:
    http://use.perl.org/~jk2addict/journal/35411

    In a nutshell, Firefox 2.x Accept header totaly screws with the REST
    controller when you use it as a base for View negotiations. If you have
    a default type of text/html pointed to a View::TT, REST will see
    text/xml from Firefox and try and send that instead, based on this header:

    text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    What does everyone think about a config option/toggle to tell REST to
    ignore the Accept header, allowing it to fall back to the default
    content-type in config when no Cntent-Type header or content-type params
    are specified?

    -=Chris
    I have a subclass of Action::Serialize that does this:

    my $default = $controller->config->{serialize}{default};
    my $pcontent_type = $c->req->preferred_content_type;
    my $content_types = $c->req->accepted_content_types_qvalue;
    my $ordered_content_types = $c->req->accepted_content_types;
    my $max_qvalue = $content_types->{$pcontent_type};
    my %max_qvalue_content_types = map {
    $content_types->{$_} eq $max_qvalue ? ($_ => $default) : ()
    } keys %$content_types;
    my $content_type = $max_qvalue_content_types{$default}
    $pcontent_type
    $c->req->content_type;
    And in a subclass of Request::REST mixed with Plugin::Flavour:

    sub preferred_content_type {
    my $self = shift;
    if ($self->flavour) {
    my $type = $self->{ext_map}{$self->flavour}
    $self->_ext_to_type($self->flavour);
    return $type;
    }
    $self->accepted_content_types->[0];
    }

    sub accepted_content_types_qvalue {
    my $self = shift;
    return $self->{content_types_qvalue} if $self->{content_types_qvalue};

    my %types;
    if ($self->method eq "GET" && $self->param('content-type')) {
    $types{ $self->param('content-type') } = 2;
    }

    # This is taken from chansen's Apache2::UploadProgress.
    if ( $self->header('Accept') ) {
    $self->accept_only(1) unless keys %types;

    my $accept_header = $self->header('Accept');
    my $counter = 0;

    foreach my $pair ( split_header_words($accept_header) ) {
    my ( $type, $qvalue ) = @{$pair}[ 0, 3 ];
    next if $types{$type};
    $qvalue = 1 unless defined $qvalue;
    $types{$type} = sprintf '%.3f', $qvalue;
    }
    }
    return $self->{content_types_qvalue} = \%types;
    }


    That way all works fine. If you add an extension to the uri (like
    .json or .xml), it serves that content-type. Else it tries to find the
    greater qvalue on the Accept Header and tries to serve that. If it has
    more than one content-type with the same max qvalue it tries to find
    the default content-type in that list and serve it. If it isn't in the
    max qvalue list than it serves the first content-type on that list.
    I think that is a sane approach.

    --
    Jonas
  • Christopher H. Laco at Jan 17, 2008 at 6:03 pm

    Jonas Alves wrote:
    On Jan 17, 2008 2:32 PM, Christopher H. Laco wrote:
    I've touched on this before, and posted about it on UP:
    http://use.perl.org/~jk2addict/journal/35411

    In a nutshell, Firefox 2.x Accept header totaly screws with the REST
    controller when you use it as a base for View negotiations. If you have
    a default type of text/html pointed to a View::TT, REST will see
    text/xml from Firefox and try and send that instead, based on this header:

    text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    What does everyone think about a config option/toggle to tell REST to
    ignore the Accept header, allowing it to fall back to the default
    content-type in config when no Cntent-Type header or content-type params
    are specified?

    -=Chris
    I have a subclass of Action::Serialize that does this:

    my $default = $controller->config->{serialize}{default};
    my $pcontent_type = $c->req->preferred_content_type;
    my $content_types = $c->req->accepted_content_types_qvalue;
    my $ordered_content_types = $c->req->accepted_content_types;
    my $max_qvalue = $content_types->{$pcontent_type};
    my %max_qvalue_content_types = map {
    $content_types->{$_} eq $max_qvalue ? ($_ => $default) : ()
    } keys %$content_types;
    my $content_type = $max_qvalue_content_types{$default}
    $pcontent_type
    $c->req->content_type;
    And in a subclass of Request::REST mixed with Plugin::Flavour:

    sub preferred_content_type {
    my $self = shift;
    if ($self->flavour) {
    my $type = $self->{ext_map}{$self->flavour}
    $self->_ext_to_type($self->flavour);
    return $type;
    }
    $self->accepted_content_types->[0];
    }

    sub accepted_content_types_qvalue {
    my $self = shift;
    return $self->{content_types_qvalue} if $self->{content_types_qvalue};

    my %types;
    if ($self->method eq "GET" && $self->param('content-type')) {
    $types{ $self->param('content-type') } = 2;
    }

    # This is taken from chansen's Apache2::UploadProgress.
    if ( $self->header('Accept') ) {
    $self->accept_only(1) unless keys %types;

    my $accept_header = $self->header('Accept');
    my $counter = 0;

    foreach my $pair ( split_header_words($accept_header) ) {
    my ( $type, $qvalue ) = @{$pair}[ 0, 3 ];
    next if $types{$type};
    $qvalue = 1 unless defined $qvalue;
    $types{$type} = sprintf '%.3f', $qvalue;
    }
    }
    return $self->{content_types_qvalue} = \%types;
    }


    That way all works fine. If you add an extension to the uri (like
    .json or .xml), it serves that content-type. Else it tries to find the
    greater qvalue on the Accept Header and tries to serve that. If it has
    more than one content-type with the same max qvalue it tries to find
    the default content-type in that list and serve it. If it isn't in the
    max qvalue list than it serves the first content-type on that list.
    I think that is a sane approach.
    Well volunteered! I can't speak for the flavour stuff, but I'd think the
    q value logic would be well served in the REST package. :-)

    I'd personally like the flavour stuff in there as well. In my case, I'm
    half way there. I have a type= that takes a friendly name (atom, rss,
    json) ... along wieh adding some of those content types to MIME::Types
    since it's missing a few of them for type->extension mapping.

    -=Chris

    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: signature.asc
    Type: application/pgp-signature
    Size: 187 bytes
    Desc: OpenPGP digital signature
    Url : http://lists.scsys.co.uk/pipermail/catalyst/attachments/20080117/d0103666/signature.pgp
  • Thomas L. Shinnick at Jan 17, 2008 at 9:10 pm

    At 12:03 PM 1/17/2008, Christopher H. Laco wrote:
    Jonas Alves wrote:
    On Jan 17, 2008 2:32 PM, Christopher H. Laco wrote:
    I've touched on this before, and posted about it on UP:
    http://use.perl.org/~jk2addict/journal/35411

    In a nutshell, Firefox 2.x Accept header totaly screws with the REST
    controller when you use it as a base for View negotiations. If you have
    a default type of text/html pointed to a View::TT, REST will see
    text/xml from Firefox and try and send that instead, based on this header:

    text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    What does everyone think about a config option/toggle to tell REST to
    ignore the Accept header, allowing it to fall back to the default
    content-type in config when no Cntent-Type header or content-type params
    are specified?

    -=Chris
    I have a subclass of Action::Serialize that does this:
    my $default = $controller->config->{serialize}{default};
    my $pcontent_type = $c->req->preferred_content_type;
    my $content_types = $c->req->accepted_content_types_qvalue;
    my $ordered_content_types = $c->req->accepted_content_types;
    my $max_qvalue = $content_types->{$pcontent_type};
    my %max_qvalue_content_types = map {
    $content_types->{$_} eq $max_qvalue ? ($_ => $default) : ()
    } keys %$content_types;
    my $content_type = $max_qvalue_content_types{$default}
    $pcontent_type
    $c->req->content_type;
    And in a subclass of Request::REST mixed with Plugin::Flavour:
    sub preferred_content_type {
    my $self = shift;
    if ($self->flavour) {
    my $type = $self->{ext_map}{$self->flavour}
    $self->_ext_to_type($self->flavour);
    return $type;
    }
    $self->accepted_content_types->[0];
    }
    sub accepted_content_types_qvalue {
    my $self = shift;
    return $self->{content_types_qvalue} if $self->{content_types_qvalue};
    my %types;
    if ($self->method eq "GET" && $self->param('content-type')) {
    $types{ $self->param('content-type') } = 2;
    }
    # This is taken from chansen's Apache2::UploadProgress.
    if ( $self->header('Accept') ) {
    $self->accept_only(1) unless keys %types;
    my $accept_header = $self->header('Accept');
    my $counter = 0;
    foreach my $pair ( split_header_words($accept_header) ) {
    my ( $type, $qvalue ) = @{$pair}[ 0, 3 ];
    next if $types{$type};
    $qvalue = 1 unless defined $qvalue;
    $types{$type} = sprintf '%.3f', $qvalue;
    }
    }
    return $self->{content_types_qvalue} = \%types;
    }

    That way all works fine. If you add an extension to the uri (like
    .json or .xml), it serves that content-type. Else it tries to find the
    greater qvalue on the Accept Header and tries to serve that. If it has
    more than one content-type with the same max qvalue it tries to find
    the default content-type in that list and serve it. If it isn't in the
    max qvalue list than it serves the first content-type on that list.
    I think that is a sane approach.
    Well volunteered! I can't speak for the flavour stuff, but I'd think
    the q value logic would be well served in the REST package. :-)

    I'd personally like the flavour stuff in there as well. In my case,
    I'm half way there. I have a type= that takes a friendly name (atom,
    rss, json) ... along wieh adding some of those content types to
    MIME::Types since it's missing a few of them for type->extension mapping.

    -=Chris
    Just wanted to note that using extensions on URIs to select
    content_type is a technique mentioned in the "RESTful Web Services"
    book. I think it was touted as a "way to be sure the right type was
    returned". I hadn't gotten to seeing if it'd work with REST stuff
    here. Color me interested ....
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20080117/29c40286/attachment.htm
  • Jonas Alves at Jan 17, 2008 at 10:35 pm

    On Jan 17, 2008 6:03 PM, Christopher H. Laco wrote:
    Jonas Alves wrote:
    On Jan 17, 2008 2:32 PM, Christopher H. Laco wrote:
    I've touched on this before, and posted about it on UP:
    http://use.perl.org/~jk2addict/journal/35411

    In a nutshell, Firefox 2.x Accept header totaly screws with the REST
    controller when you use it as a base for View negotiations. If you have
    a default type of text/html pointed to a View::TT, REST will see
    text/xml from Firefox and try and send that instead, based on this header:

    text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    What does everyone think about a config option/toggle to tell REST to
    ignore the Accept header, allowing it to fall back to the default
    content-type in config when no Cntent-Type header or content-type params
    are specified?

    -=Chris
    I have a subclass of Action::Serialize that does this:

    my $default = $controller->config->{serialize}{default};
    my $pcontent_type = $c->req->preferred_content_type;
    my $content_types = $c->req->accepted_content_types_qvalue;
    my $ordered_content_types = $c->req->accepted_content_types;
    my $max_qvalue = $content_types->{$pcontent_type};
    my %max_qvalue_content_types = map {
    $content_types->{$_} eq $max_qvalue ? ($_ => $default) : ()
    } keys %$content_types;
    my $content_type = $max_qvalue_content_types{$default}
    $pcontent_type
    $c->req->content_type;
    And in a subclass of Request::REST mixed with Plugin::Flavour:

    sub preferred_content_type {
    my $self = shift;
    if ($self->flavour) {
    my $type = $self->{ext_map}{$self->flavour}
    $self->_ext_to_type($self->flavour);
    return $type;
    }
    $self->accepted_content_types->[0];
    }

    sub accepted_content_types_qvalue {
    my $self = shift;
    return $self->{content_types_qvalue} if $self->{content_types_qvalue};

    my %types;
    if ($self->method eq "GET" && $self->param('content-type')) {
    $types{ $self->param('content-type') } = 2;
    }

    # This is taken from chansen's Apache2::UploadProgress.
    if ( $self->header('Accept') ) {
    $self->accept_only(1) unless keys %types;

    my $accept_header = $self->header('Accept');
    my $counter = 0;

    foreach my $pair ( split_header_words($accept_header) ) {
    my ( $type, $qvalue ) = @{$pair}[ 0, 3 ];
    next if $types{$type};
    $qvalue = 1 unless defined $qvalue;
    $types{$type} = sprintf '%.3f', $qvalue;
    }
    }
    return $self->{content_types_qvalue} = \%types;
    }


    That way all works fine. If you add an extension to the uri (like
    .json or .xml), it serves that content-type. Else it tries to find the
    greater qvalue on the Accept Header and tries to serve that. If it has
    more than one content-type with the same max qvalue it tries to find
    the default content-type in that list and serve it. If it isn't in the
    max qvalue list than it serves the first content-type on that list.
    I think that is a sane approach.
    Well volunteered! I can't speak for the flavour stuff, but I'd think the
    q value logic would be well served in the REST package. :-)

    I'd personally like the flavour stuff in there as well. In my case, I'm
    half way there. I have a type= that takes a friendly name (atom, rss,
    json) ... along wieh adding some of those content types to MIME::Types
    since it's missing a few of them for type->extension mapping.
    Well, I don't mind to help in that too. I think that the flavour stuff
    is very useful. Especially if you need to use the REST interface from
    some lib/framework/api where isn't easy to set the Accept header. And
    I think that is much more clean than the query-string type parameter.

    --
    Jonas
  • Adam Jacob at Jan 18, 2008 at 8:46 pm
    Jonas,

    Myself, Jshirley, or Claco would gladly take patches to C::A::REST to
    add this functionality. Send us the patch, and we'll get it tested
    and out the door.

    Adam
    On 1/17/08, Jonas Alves wrote:
    On Jan 17, 2008 6:03 PM, Christopher H. Laco wrote:

    Jonas Alves wrote:
    On Jan 17, 2008 2:32 PM, Christopher H. Laco wrote:
    I've touched on this before, and posted about it on UP:
    http://use.perl.org/~jk2addict/journal/35411

    In a nutshell, Firefox 2.x Accept header totaly screws with the REST
    controller when you use it as a base for View negotiations. If you have
    a default type of text/html pointed to a View::TT, REST will see
    text/xml from Firefox and try and send that instead, based on this header:

    text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5

    What does everyone think about a config option/toggle to tell REST to
    ignore the Accept header, allowing it to fall back to the default
    content-type in config when no Cntent-Type header or content-type params
    are specified?

    -=Chris
    I have a subclass of Action::Serialize that does this:

    my $default = $controller->config->{serialize}{default};
    my $pcontent_type = $c->req->preferred_content_type;
    my $content_types = $c->req->accepted_content_types_qvalue;
    my $ordered_content_types = $c->req->accepted_content_types;
    my $max_qvalue = $content_types->{$pcontent_type};
    my %max_qvalue_content_types = map {
    $content_types->{$_} eq $max_qvalue ? ($_ => $default) : ()
    } keys %$content_types;
    my $content_type = $max_qvalue_content_types{$default}
    $pcontent_type
    $c->req->content_type;
    And in a subclass of Request::REST mixed with Plugin::Flavour:

    sub preferred_content_type {
    my $self = shift;
    if ($self->flavour) {
    my $type = $self->{ext_map}{$self->flavour}
    $self->_ext_to_type($self->flavour);
    return $type;
    }
    $self->accepted_content_types->[0];
    }

    sub accepted_content_types_qvalue {
    my $self = shift;
    return $self->{content_types_qvalue} if $self->{content_types_qvalue};

    my %types;
    if ($self->method eq "GET" && $self->param('content-type')) {
    $types{ $self->param('content-type') } = 2;
    }

    # This is taken from chansen's Apache2::UploadProgress.
    if ( $self->header('Accept') ) {
    $self->accept_only(1) unless keys %types;

    my $accept_header = $self->header('Accept');
    my $counter = 0;

    foreach my $pair ( split_header_words($accept_header) ) {
    my ( $type, $qvalue ) = @{$pair}[ 0, 3 ];
    next if $types{$type};
    $qvalue = 1 unless defined $qvalue;
    $types{$type} = sprintf '%.3f', $qvalue;
    }
    }
    return $self->{content_types_qvalue} = \%types;
    }


    That way all works fine. If you add an extension to the uri (like
    .json or .xml), it serves that content-type. Else it tries to find the
    greater qvalue on the Accept Header and tries to serve that. If it has
    more than one content-type with the same max qvalue it tries to find
    the default content-type in that list and serve it. If it isn't in the
    max qvalue list than it serves the first content-type on that list.
    I think that is a sane approach.
    Well volunteered! I can't speak for the flavour stuff, but I'd think the
    q value logic would be well served in the REST package. :-)

    I'd personally like the flavour stuff in there as well. In my case, I'm
    half way there. I have a type= that takes a friendly name (atom, rss,
    json) ... along wieh adding some of those content types to MIME::Types
    since it's missing a few of them for type->extension mapping.
    Well, I don't mind to help in that too. I think that the flavour stuff
    is very useful. Especially if you need to use the REST interface from
    some lib/framework/api where isn't easy to set the Accept header. And
    I think that is much more clean than the query-string type parameter.

    --
    Jonas

    _______________________________________________
    List: Catalyst@lists.scsys.co.uk
    Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
    Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
    Dev site: http://dev.catalyst.perl.org/

    --
    HJK Solutions - We Launch Startups - http://www.hjksolutions.com
    Adam Jacob, Senior Partner
    T: (206) 508-4759 E: adam@hjksolutions.com
  • Jonas Alves at Jan 22, 2008 at 11:24 am

    On Jan 18, 2008 8:46 PM, Adam Jacob wrote:
    Jonas,

    Myself, Jshirley, or Claco would gladly take patches to C::A::REST to
    add this functionality. Send us the patch, and we'll get it tested
    and out the door.

    Adam
    Hi Adam,
    I started to write a patch some time ago, just need some docs and
    tests. But right now I don't have time to finish it. Maybe next week.
    :)

    --
    Jonas

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupcatalyst @
categoriescatalyst, perl
postedJan 17, '08 at 2:32p
activeJan 22, '08 at 11:24a
posts7
users4
websitecatalystframework.org
irc#catalyst

People

Translate

site design / logo © 2022 Grokbase