From 027aa3b389378d7cb5f2913a8c3b3ab7d3744b25 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Sun, 16 Dec 2018 09:08:33 +0100 Subject: Rename mode=marudor to mode=json as it is no longer used by marudor.de mode=marudor requests will be silently handled as mode=json so as not to break other clients --- index.pl | 61 ++++++++++++++------------------------- t/22-json.t | 46 +++++++++++++++++++++++++++++ t/22-marudor.t | 46 ----------------------------- templates/layouts/default.html.ep | 6 ++-- 4 files changed, 71 insertions(+), 88 deletions(-) create mode 100644 t/22-json.t delete mode 100644 t/22-marudor.t diff --git a/index.pl b/index.pl index 39692ae..d7e3f9c 100644 --- a/index.pl +++ b/index.pl @@ -188,7 +188,7 @@ helper 'handle_no_results_json' => sub { } ); } - elsif ( $backend eq 'iris' ) { + else { my @candidates = map { { code => $_->[0], name => $_->[1] } } Travel::Status::DE::IRIS::Stations::get_station($station); if ( @candidates > 1 @@ -213,15 +213,6 @@ helper 'handle_no_results_json' => sub { ); } } - else { - $json = $self->render_to_string( - json => { - api_version => $api_version, - version => $VERSION, - error => ( $errstr // 'unknown station code/name' ) - } - ); - } if ($callback) { $self->render( data => "$callback($json);", @@ -358,8 +349,23 @@ sub handle_request { $self->stash( layout => 'text' ); } + # Historically, there were two JSON APIs: 'json' (undocumented, raw + # passthrough of serialized Travel::Status::DE::IRIS::Result / + # Travel::Status::DE::DE::HAFAS::Result objects) and 'marudor' + # (documented, IRIS only, stable versioned API). The latter was initially + # created for marudor.de, but quickly used by other clients as well. + # + # marudor.de switched to a nodejs IRIS parser in December 2018. As the + # 'json' API was not used and the 'marudor' variant is no longer related to + # (or used by) marudor.de, it was renamed to 'json'. Many clients won't + # notice this for year to come, so we make sure mode=marudor still works as + # intended. + if ($template eq 'marudor') { + $template = 'json'; + } + if ( - not( $template ~~ [qw[app infoscreen json marudor multi single text]] ) + not( $template ~~ [qw[app infoscreen json multi single text]] ) ) { $template = 'app'; @@ -382,7 +388,7 @@ sub handle_request { return; } - if ( $template eq 'marudor' ) { + if ( $template eq 'json' ) { $backend = 'iris'; $opt{lookahead} = 120; } @@ -397,7 +403,7 @@ sub handle_request { my $errstr = $data->{errstr}; my @results = @{$results_ref}; - if ( not @results and $template ~~ [qw[json marudor]] ) { + if ( not @results and $template eq 'json' ) { $self->handle_no_results_json( $backend, $station, $errstr, $api_version, $callback ); return; @@ -530,7 +536,7 @@ sub handle_request { . $additional_line . ( $info ? ' +++ ' : q{} ) . $info; - if ( $template ne 'marudor' ) { + if ( $template ne 'json' ) { push( @{$moreinfo}, [ 'Zusätzliche Halte', $additional_line ] @@ -545,7 +551,7 @@ sub handle_request { . $cancel_line . ( $info ? ' +++ ' : q{} ) . $info; - if ( $template ne 'marudor' ) { + if ( $template ne 'json' ) { push( @{$moreinfo}, [ 'Ohne Halt in', $cancel_line ] ); } } @@ -602,7 +608,7 @@ sub handle_request { $info =~ s{ (?: ca [.] \s* )? [+] (\d+) }{Verspätung ca $1 Min.}x; } - if ( $template eq 'marudor' ) { + if ( $template eq 'json' ) { my @json_route = $self->json_route_diff( [ $result->route ], [ $result->sched_route ] ); @@ -861,29 +867,6 @@ sub handle_request { } if ( $template eq 'json' ) { - $self->res->headers->access_control_allow_origin(q{*}); - my $json = $self->render_to_string( - json => { - api_version => $api_version, - preformatted => \@departures, - version => $VERSION, - raw => \@results, - } - ); - if ($callback) { - $self->render( - data => "$callback($json);", - format => 'json' - ); - } - else { - $self->render( - data => $json, - format => 'json' - ); - } - } - elsif ( $template eq 'marudor' ) { $self->res->headers->access_control_allow_origin(q{*}); my $json = $self->render_to_string( json => { diff --git a/t/22-json.t b/t/22-json.t new file mode 100644 index 0000000..9db67b8 --- /dev/null +++ b/t/22-json.t @@ -0,0 +1,46 @@ +#!/usr/bin/env perl +use strict; +use warnings; +use 5.014; +use Test::More; +use Test::Mojo; + +use FindBin; +require "$FindBin::Bin/../index.pl"; + +my $t = Test::Mojo->new; + +# Note: These tests depends on IRIS live data. If it fails, it -might- also +# be because of IRIS problems or unanticipated schedule changes. +# TODO: Support mock XML from hard disk. + +$t->get_ok('/EDUV?mode=json&version=1') + ->status_is(200) + ->json_has('/departures', 'has departures') + ->json_has('/departures/0', 'has a departure') + ->json_has('/departures/0/route', '.route') + ->json_has('/departures/0/delay', '.delay') + ->json_like('/departures/0/destination', + qr{ ^ (Dortmund|Bochum|Essen|D.sseldorf|Solingen) \s Hbf $}x, + '.destination') + ->json_like('/departures/0/isCancelled', qr{ ^ 0 | 1 $ }x, '.is_cancelled') + ->json_has('/departures/0/messages', '.messages') + ->json_has('/departures/0/messages/delay', '.messages.delay') + ->json_has('/departures/0/messages/qos', '.messages.qos') + ->json_like('/departures/0/time', qr{ ^ \d \d? : \d\d $ }x, '.time') + ->json_is('/departures/0/train', 'S 1', '.train') + ->json_like('/departures/0/platform', qr{ ^ 1 | 2 $}x, '.platform') + ->json_like('/departures/0/route/0/name', + qr{ ^ (Dortmund|Bochum|Essen|D.sseldorf|Solingen) \s Hbf $}x, + '.route[0]') + ->json_like('/departures/0/via/0', + qr{ ^ Dortmund-Dorstfeld \s S.d | Dortmund-Oespel $}x, + '.via[0]') + ; + +$t->get_ok('/EDUV?mode=json&version=1&callback=my_callback') + ->status_is(200) + ->content_like(qr{ ^ my_callback \( }x, 'json callback works'); +# ) <- just here to fix bracket grouping in vim + +done_testing(); diff --git a/t/22-marudor.t b/t/22-marudor.t deleted file mode 100644 index 7038ca6..0000000 --- a/t/22-marudor.t +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env perl -use strict; -use warnings; -use 5.014; -use Test::More; -use Test::Mojo; - -use FindBin; -require "$FindBin::Bin/../index.pl"; - -my $t = Test::Mojo->new; - -# Note: These tests depends on IRIS live data. If it fails, it -might- also -# be because of IRIS problems or unanticipated schedule changes. -# TODO: Support mock XML from hard disk. - -$t->get_ok('/EDUV?mode=marudor&version=1') - ->status_is(200) - ->json_has('/departures', 'has departures') - ->json_has('/departures/0', 'has a departure') - ->json_has('/departures/0/route', '.route') - ->json_has('/departures/0/delay', '.delay') - ->json_like('/departures/0/destination', - qr{ ^ (Dortmund|Bochum|Essen|D.sseldorf|Solingen) \s Hbf $}x, - '.destination') - ->json_like('/departures/0/isCancelled', qr{ ^ 0 | 1 $ }x, '.is_cancelled') - ->json_has('/departures/0/messages', '.messages') - ->json_has('/departures/0/messages/delay', '.messages.delay') - ->json_has('/departures/0/messages/qos', '.messages.qos') - ->json_like('/departures/0/time', qr{ ^ \d \d? : \d\d $ }x, '.time') - ->json_is('/departures/0/train', 'S 1', '.train') - ->json_like('/departures/0/platform', qr{ ^ 1 | 2 $}x, '.platform') - ->json_like('/departures/0/route/0/name', - qr{ ^ (Dortmund|Bochum|Essen|D.sseldorf|Solingen) \s Hbf $}x, - '.route[0]') - ->json_like('/departures/0/via/0', - qr{ ^ Dortmund-Dorstfeld \s S.d | Dortmund-Oespel $}x, - '.via[0]') - ; - -$t->get_ok('/EDUV?mode=marudor&version=1&callback=my_callback') - ->status_is(200) - ->content_like(qr{ ^ my_callback \( }x, 'json callback works'); -# ) <- just here to fix bracket grouping in vim - -done_testing(); diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 3edb715..0d70092 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -214,10 +214,10 @@ nur Züge via Bochum oder Hamm) "App"-Frontend verwenden (und vorerst den Parameter force_mobile=1 hinzufügen, das ist bald aber nicht mehr nötig). Für eine große Ansicht (z.B. als alleinstehender Infoscreen) gibt es das "Infoscreen"-Frontend. -
  • Die Parameter mode=marudor&version=3 - liefern ein JSON-Interface. Die route-Elemente können zusätzlich +
  • Die Parameter mode=json&version=3 + bieten ein JSON-Interface. Die route-Elemente können zusätzlich die Felder "isAdditional" oder "isCancelled" enthalten, der Rest sollte - selbsterklärend sein.
  • + selbsterklärend sein. Dieses Interface nutzt ausschließlich das IRIS-Backend.
  • Dieser Dienst ist Open Source-Software (Links siehe unten) und kann auch auf eigenen Servern installiert werden. Automatisierte Crawler, die mehrere Dutzend Stationen pro Minute abfragen, bitte nur auf eigenen Instanzen -- cgit v1.2.3