Geo-OGC-Service

 view release on metacpan or  search on metacpan

lib/Geo/OGC/Service.pm  view on Meta::CPAN

    my $config = shift;
    my $had_ref;
    do {
        $had_ref = 0;
        for my $j (keys %$config) {
            $had_ref += config_ref($config->{$j}, $config);
        }
    } while ($had_ref);
    for my $j (keys %$config) {
        next if $j eq 'Common';
        next if $j =~ /^BoundingBox/;
        next unless ref $config->{$j} eq 'HASH';
        for my $c (keys %{$config->{Common}}) {
            $config->{$j}{$c} //= clone($config->{Common}{$c});
        }
    }
}

sub config_ref {
    my ($config, $refs) = @_;
    my $had_ref = 0;
    if (ref $config eq 'ARRAY') {
        for my $j (@$config) {
            $had_ref += config_ref($j, $refs);
        }
    }
    elsif (ref $config eq 'HASH') {
        for my $j (keys %$config) {
            my $r = $config->{$j};
            if (ref $r) {
                $had_ref += config_ref($r, $refs);
            } else {
                if ($r =~ /^ref:/) {
                    my $target = config_target($refs, $r);
                    croak "config reference not found: '$r'." unless $target;
                    $config->{$j} = clone($target);
                    $had_ref = 1;
                }
            }
        }
    }
    return $had_ref;
}

sub config_target {
    my ($config, $ref) = @_;
    my @path = split /\//, $ref;
    shift @path;
    if (ref $config eq 'HASH') {
        return $config->{$path[0]};
    }
    return undef;
}

=pod

=head3 call

This method is called internally by the method to_app of
Plack::Component. The method fails unless this module
is running in a psgi.streaming environment. Otherwise,
it returns a subroutine, which calls the respond method.

=cut

sub call {
    my ($self, $env) = @_;
    if (! $env->{'psgi.streaming'}) { # after Lyra-Core/lib/Lyra/Trait/Async/PsgiApp.pm
        return [ 500, ["Content-Type" => "text/plain"], ["Internal Server Error (Server Implementation Mismatch)"] ];
    }
    return sub {
        my $responder = shift;
        $self->respond($responder, $env);
    }
}

=pod

=head3 respond

This method is called for each request from the Internet. The call is
responded during the execution of the subroutine.

In the default case this method constructs a new service object using
the method 'service' and calls its process_request method with PSGI
style $responder object as a parameter.

This subroutine may fail while interpreting the request, or while
processing the request.

=cut

sub respond {
    my ($self, $responder, $env) = @_;
    # TODO: logging
    if ($env->{REQUEST_METHOD} eq 'OPTIONS') {
        $responder->([200, ['Content-Length' => 0,
                            'Content-Type' => 'text/plain', 
                            Geo::OGC::Service::Common::CORS($self)]]);
    } else {
        my $service;
        eval {
            $service = $self->service($responder, $env);
        };
        if ($@) {
            print STDERR "$@";
            error($responder, { exceptionCode => 'ResourceNotFound',
                                ExceptionText => "Internal error while interpreting the request." } );
        } elsif ($service) {
            eval {
                $service->process_request($responder);
            };
            if ($@) {
                print STDERR "$@";
                error($responder, { exceptionCode => 'ResourceNotFound',
                                    ExceptionText => "Internal error while processing the request." } );
            }
        }
    }
}

=pod

=head3 service

This method does a preliminary interpretation of the request and
converts it into a service object, which is returned. 



( run in 1.550 second using v1.01-cache-2.11-cpan-140bd7fdf52 )