Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Re: Help choosing the most efficient, dependable condition(al)

by daxim (Chaplain)
on Nov 13, 2013 at 19:02 UTC ( #1062431=note: print w/ replies, xml ) Need Help??


in reply to Help choosing the most efficient, dependable condition(al)

That regex match is wrong. HTTP defines how you must negotiate a content type. Correct code:

use strictures;
use HTTP::Negotiate qw(choose);

# play with the quality
#  values here ↓
#              ↓
#              ↓
if ('xhtml' eq choose([
    [ xhtml => 1 => 'application/xhtml+xml' ],
    [ html =>  1 => 'text/html' ]
])) {
    print "Content-Type: application/xhtml+xml; charset=UTF-8\n";
} else {
    print "Content-Type: text/html; charset=UTF-8\n";
}
print "Vary: Accept\n"; # tell caches this resource has several representations

demo:

HTTP_ACCEPT='text/html; q=0.5, application/xhtml+xml; q=0.2' perl pm1062426.pl
HTTP_ACCEPT='text/html; q=0.5, application/xhtml+xml; q=0.8' perl pm1062426.pl
HTTP_ACCEPT='text/html, application/xhtml+xml' perl pm1062426.pl
HTTP_ACCEPT='text/html' perl pm1062426.pl
HTTP_ACCEPT='text/html, text/plain; q=0.5' perl pm1062426.pl
HTTP_ACCEPT='application/xhtml+xml' perl pm1062426.pl
HTTP_ACCEPT='application/xhtml+xml, application/xml, text/html, text/plain; q=0.1' perl pm1062426.pl

Update: add the Vary header, fix a header syntax error in demo line 5


Comment on Re: Help choosing the most efficient, dependable condition(al)
Re^2: Help choosing the most efficient, dependable condition(al)
by taint (Chaplain) on Nov 13, 2013 at 19:31 UTC
    Greetings daxim, and thank you very much for all the time, and effort you put into this.

    You're test seem conclusive. But isn't using/requiring a Module a bit overkill?
    I mean, doesn't perl already provide sufficient method(s) to accomplish such goals?

    Maybe I'm wrong. But having used the method I posted here for some 2 years now. I haven't seen any evidence that there were any issues with it, except to the extent that an occasional "Use of uninitialized value $ENV{"HTTP_ACCEPT"}" would show up in the error log(s).

    I'm not trying to say that method is right. I'm just (while impressive) not sure that doing it correctly requires using an extra Module

    Thank you again daxim for all your time, and effort on this.

    --Chris

    #!/usr/bin/perl -Tw
    use Perl::Always or die;
    my $perl_version = (5.12.5);
    print $perl_version;
      But isn't using/requiring a Module a bit overkill?

      No. This kind of thinking is exactly what makes maintaining old code such a burden.

      I mean, doesn't perl already provide sufficient method(s) to accomplish such goals?

      So does C, and COBOL, and Assembly. Dovetailed with the above we get: Isnít using a high level language overkill?

        "No. This kind of thinking is exactly what makes maintaining old code such a burden."

        Huh? How does choosing Perl's internals as opposed to using a Module == "maintaining old code such a burden"?

        "So does C, and COBOL, and Assembly. Dovetailed with the above we get: Isnít using a high level language overkill?"

        OK now you've completely lost me. I suggest using Perl. Your assertion suggests that using Perl (a "high level language") is ridiculous to consider, when using with Perl.

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;
      thank you very much for all the time, and effort you put into this.
      Thank the libwww-perl authors, they did all the hard work of translating the algorithm into code and releasing it. I just remembered that this module exists, and adapted its documentation synopsis for your circumstance.
      But isn't using/requiring a Module a bit overkill?
      No. It does exactly what it needs to do, no less, barely more. You would not save much memory if you were to reimplement it from scratch.
      doesn't perl already provide sufficient method(s) to accomplish such goals?
      No, there is no negotiate function baked into Perl, being a general-purpose language. Maybe PHP has it, that would make sense given its Web deployment niche.
      having used the method I posted here for some 2 years now. I haven't seen any evidence that there were any issues with it
      This is not rational. Past evidence makes no promise about future performance. I can easily construct a case where the naive regex match breaks down, and the case wouldn't even be degenerate. Hint: that match ignores the q value.

      In any case, this is not how a specification works. As part of the Internet, you have entered into this consensus/social contract to follow the specs. Either you are compliant, and gain interoperability, or you don't follow it, and the rest of the Internet treats you as RFC-ignorant/damage and routes around. Don't be that guy who does it on purpose, there's enough trouble already with unintentional bugs. (I had a bug in the code I showed thread-upwards, see the update.)

      doing it correctly requires using an extra Module
      It's free software, you can just copy the code into your project, so you have the functionality, but not a module. I generally don't do so because that approach harder to maintain. I like the abstraction modules gives me, and Perl's dependency management is outstanding. Why are you uneay about using a module as it is? Where do you draw the line what's acceptable and what not?
        SOLD!

        You must be a salesmen -- and a good one, at that daxim!

        I'm all in -- on this one, anyway.

        I really appreciate all the time, and effort you put into elaborating this for me. You made a really good case for it's usage (the Module).

        I often struggle with KISS (Keep It Simple Stupid). Now that can go two ways; on one hand, it's really simple to make use of a Module, and it makes development, and time, a snap.

        But what about flow. I mean keeping it linear, or synchronous. Things look easy to follow, are a snap to diagnose, and generally run faster. Warning; I should probably confess; I started programming in assembler -- see; was my first language.

        Anyhow, because of this way of thinking that have (flow). I curse those that espouse OO, and all it's gloriousness. I remember hearing about it when it first started, back in the early '90's, and thought; boy, somebody sure bought the bill of goods there. H3ll, the closes thing to OO in assembler, is a macro.

        OK I guess it has advantages in large applications. But I still look at it with a great deal of scrutiny. So I guess this line of thinking might be considered by some, to be a hindrance. But that's the way it is with me, until I'm convinced otherwise, I guess.

        I'd really like to thank you again daxim, for all the time, and effort you put into this. Thanks.

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;

      But isn't using/requiring a Module a bit overkill?

      HTTP::Negotiate has passed smoke testing on 4244 systems, and failed on one, which was probably misconfigured. Those systems include Perl versions from 5.8.1 through 5.19.6, on operating systems including Window (cygwin), Mac, DragonflyBSD, FreeBSD, GNU Hurd, Debian, Haiku, GNU Linux, MidnightBSD, MirOS BSD, Win32, NetBSD, QNX Neutrino, OpenBSD, and Sun/Solaris. It is used in production, probably in many instances. Its test suite, while minimal, exists, and works.

      HTTP::Negotiate "...provides a complete implementation of the HTTP content negotiation algorithm specified in draft-ietf-http-v11-spec-00.ps chapter 12." And it's been around since 1996. It currently has one bug report in its RT, relating to a typo in the POD. It has POD.

      You have an if statement with a fragile regular expression. ...I'm sorry, what was your question again? ;)

      I mean, doesn't perl already provide sufficient method(s) to accomplish such goals?

      Yes. HTTP::Negotiate is written in pure-Perl. Perl is capable of facilitating the implementation of standards compliant HTTP negotiation. Your code doesn't do that.

      When the phone rings, I want to pick up a device that I can push the "answer" button on, hold to my ear, and hear the caller's voice. I don't want to pick up a heap of wires and chips on a breadboard and hold my hand to a grounding plate with a crystal earphone from radio shack in my ear. Well, maybe if I'm in a "hobby" mood I do. But when I want it to work reliably, I use the well tested, well engineered device, not the cobbled apparatus.

      Programmers love to program, just like salespeople love to talk. Sometimes we have to temper that with a splash of Perlish lazyness.


      Dave

        LOL

        Well stated, davido!

        You've really cleared things up; and in such a delightful way, to boot!

        ++ to you, when I get some votes again!

        Thanks.

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;
Re^2: Help choosing the most efficient, dependable condition(al)
by taint (Chaplain) on Nov 13, 2013 at 21:36 UTC
    Greetings daxim.

    FWIW, there's an issue with your example above:

    # your version print "Content-Type: application/xhtml+xml; charset=UTF-8\n"; } else { print "Content-Type: text/html; charset=UTF-8\n"; # MY version print "Content-Type: application/xhtml+xml; charset=UTF-8\n\n"; } else { print "Content-Type: text/html; charset=UTF-8\n\n";
    For the record; it takes 2 newlines (\n\n).
    :)

    --Chris

    #!/usr/bin/perl -Tw
    use Perl::Always or die;
    my $perl_version = (5.12.5);
    print $perl_version;
      Not if send another header, namely "Vary". See the code update in Re: Help choosing the most efficient, dependable condition(al)

      There's a lot to be gained by using a Web framework (you are familiar with CGI.pm, try Plack::Request/Plack::Response), where one doesn't have to care about newlines at all - the software handles the correct formatting for me. Short example: plackup -MPlack::Request -e'sub { my $req = Plack::Request->new(shift); return $req->new_response(200, [Content_Type => "text/html", Vary => "Accept"], [])->finalize }'

      Doing the formatting manually and needing to get it correct is the real overhead. The work time of a programmer is expensive.

        In my humble defense daxim.

        When I use your revised edition, Perl throws:

        malformed header from script. Bad header=<?xml version="1.0" encoding= +": vary-test.cgi
        But, if I simply add an additional \n to each of the content-type lines:
        print "Content-Type: application/xhtml+xml; charset=UTF-8\n\n"; } else { print "Content-Type: text/html; charset=UTF-8\n\n";
        no errors thrown.

        I've been meaning to have a look at plackup. I've seen alot of people using it.

        Thanks for mentioning it.

        --Chris

        #!/usr/bin/perl -Tw
        use Perl::Always or die;
        my $perl_version = (5.12.5);
        print $perl_version;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://1062431]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (7)
As of 2014-08-29 17:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (283 votes), past polls