App-DuckPAN

 view release on metacpan or  search on metacpan

lib/App/DuckPAN/Web.pm  view on Meta::CPAN

	my $response = $self->request($app, $request);
	return $response->finalize;
}

my $has_common_js = 0;
sub request {
	my ( $self, $app, $request ) = @_;
	my $hostname = $self->server_hostname;
	my @path_parts = split(/\/+/,$request->request_uri);
	shift @path_parts;
	my $response = Plack::Response->new(200);
	my $body;

	if ($request->request_uri eq "/"){
		$response->content_type("text/html");
		$body = $self->page_root;
	}
	elsif (@path_parts && $path_parts[0] eq 'share') {
		my $share_dir;
		for (keys %{$self->_share_dir_hash}) {
			if ($request->path =~ m|^/$_/|g) {

				$share_dir = $_;
				# Get filename from path and url unescape
				my $filename = uri_unescape( pop @path_parts );
				# Trim path from left to right to find parent dir of filename
				# e.g /share/goodie/foo/foo_imgs/image.png -> "foo_imgs"
				my $remainder = $request->path_info;
				$remainder =~ s|$share_dir||;
				$remainder =~ s|$filename||;
				$remainder =~ s|//|/|;
				$remainder =~ s|^/\d{3,4}||;

				# if valid remainder exists, prepend to filename
				$filename = "$remainder$filename" if $remainder ne $filename;

				if (my $filename_path = $self->_share_dir_hash->{$share_dir}->can('share')->($filename)) {

					my $content_type = Plack::MIME->mime_type($filename);
					$response->content_type($content_type);

					if ($filename =~ /\.js$/ && $has_common_js &&
						$request->path =~ /(share\/spice\/([^\/]+)\/?)(.*)/){

						my $parent_dir = $1;
						my $parent_name = $2;
						my $common_js = $parent_dir."$parent_name.js";

						$body = path($common_js)->slurp;
						print "\nAppended $common_js to $filename\n\n";
					}

					$body .= path($filename_path)->slurp;
				}
				else {
					$share_dir = undef;
				}
			}
		}
		unless ($share_dir){
			$response->status(404);
			my $path = join "/", @path_parts;
			my $errormsg = "ERROR: File not found - $path";
			print "\n" . $errormsg . "\n";
			$body = $errormsg;
		}
	}
	elsif (@path_parts && $path_parts[0] eq 'js' && $path_parts[1] eq 'spice') {
		my $rewrite;
		for (keys %{$self->_path_hash}) {
			if ($request->request_uri =~ m/^$_/g) {
				my $path_remainder = $request->request_uri;
				$path_remainder =~ s/^$_//;
				$path_remainder =~ s/\/+/\//g;
				$path_remainder =~ s/^\///;
				my $spice_class = $self->_path_hash->{$_};
				$rewrite = $self->_rewrite_hash->{$spice_class};
				die "Spice tested here must have a rewrite..." unless $rewrite;
				my $from = $rewrite->from;
				my $re = $rewrite->has_from ? qr{$from} : qr{(.*)};
				if (my @captures = $path_remainder =~ m/$re/) {
					my $to = $rewrite->parsed_to;
					my $post_body = $rewrite->post_body;
					for (1..@captures) {
						my $index = $_-1;
						my $cap_from = '\$'.$_;
						my $cap_to = $captures[$index];
						if (defined $cap_to) {
							$to =~ s/$cap_from/$cap_to/g;
							$post_body =~ s/$cap_from/$cap_to/g if $post_body;
						}
						else {
							$to =~ s/$cap_from//g;
							$post_body =~ s/$cap_from//g;
						}
					}
					# Make sure we replace "${dollar}" with "$".
					$to =~ s/\$\{dollar\}/\$/g;

					my ($wrap_jsonp_callback, $callback, $wrap_string_callback, $missing_envs, $headers) =
						($rewrite->wrap_jsonp_callback, $rewrite->callback, $rewrite->wrap_string_callback, defined($rewrite->missing_envs), $rewrite->headers);

					# Check if environment variables (most likely the API key) is missing.
					# If it is missing, switch to the DDG endpoint.
					my ($use_ddh, $request_uri);
					if ($missing_envs) {
						++$use_ddh;
						$request_uri = $request->request_uri;
						 # Display the URL that we used.
						 print "\nAPI key not found. Using DuckDuckGo's endpoint:\n";
					}

					$to = "https://beta.duckduckgo.com$request_uri" if $use_ddh;

					my $h = HTTP::Headers->new( %$headers );
					my $res;
					my $req;

					if ( $post_body && !$use_ddh ) {
						$req = HTTP::Request->new(
							POST => $to,
							$h,
							$post_body
						);
					}
					else {
						$req = HTTP::Request->new(
							GET => $to,
							$h
						);
					}

					p($req->as_string);
					$res = $self->ua->request($req);

					if ($res->is_success) {
						$body = $res->decoded_content;
						# Encode utf8 api_responses to bytestream for Plack.
						utf8::encode $body if utf8::is_utf8 $body;
						warn "Cannot use wrap_jsonp_callback and wrap_string callback at the same time!" if $wrap_jsonp_callback && $wrap_string_callback;
						if ($wrap_jsonp_callback && $callback) {
							$body = $callback.'('.$body.');' unless $missing_envs;
						}
						elsif ($wrap_string_callback && $callback) {
							$body =~ s/"/\\"/g;
							$body =~ s/\n/\\n/g;
							$body =~ s/\R//g;
							$body = qq{$callback("'.$body.'");} unless $missing_envs;
						}
						$response->code($res->code);
						$response->content_type($res->content_type);
					}
					else {
						p($res->status_line, color => { string => 'red' });
						my $errormsg = (pop @{[split'::', $spice_class]}). ": ".$res->status_line;
						$body = '$("#message").removeClass("is-hidden").append("<div class=\"msg msg--warning\">'. $errormsg .'</div>");';
					}
				}
			}
		}
		unless ($rewrite){
			$response->status(404);
			my $path = join "/", @path_parts;
			my $errormsg = "ERROR: Rewrite not found - $path";
			print "\n" . $errormsg . "\n";
			$body = $errormsg;
		}
	}
	elsif ($request->param('duckduckhack_ignore')) {
		$response->status(204);
		$body = "";
	}
	elsif ($request->param('duckduckhack_css')) {
		$response->content_type('text/css');
		$body = $self->page_css;
	}
	elsif ($request->param('duckduckhack_js')) {
		$response->content_type('text/javascript');
		$body = $self->page_js;
	}
	elsif ($request->param('duckduckhack_locales')) {
		$response->content_type('text/javascript');
		$body = $self->page_locales;
	}
	elsif ($request->param('duckduckhack_templates')) {
		$response->content_type('text/javascript');
		$body = $self->page_templates;
	}
	elsif ($request->param('q') && $request->path_info eq '/') {
		my $query = $request->param('q');
		$query =~ s/^\s+|\s+$//g; # strip leading & trailing whitespace
		Encode::_utf8_on($query);
		my $ddg_request = DDG::Request->new(
			query_raw => $query,
			location => test_location_by_env(),
			language => test_language_by_env(),
		);

		my @results = ();
		my @calls_nrj = ();
		my @calls_nrc = ();
		my @calls_script = ();
		my %calls_template = ();
		my @calls_goodie;
		my @calls_fathead;
		my @ids;

		my $page = $self->page_spice;
		my $uri_encoded_query = uri_escape_utf8($query, "^A-Za-z");
		my $html_encoded_query = encode_entities($query);
		my $uri_encoded_ddh = quotemeta(uri_escape('duckduckhack-template-for-spice2', "^A-Za-z0-9"));
		$page =~ s/duckduckhack-template-for-spice2/$html_encoded_query/g;
		$page =~ s/$uri_encoded_ddh/$uri_encoded_query/g;

		# For debugging query replacement.
		#p($uri_encoded_ddh);
		#p($page);

		my $root = HTML::TreeBuilder->new;
		$root->parse($page);




( run in 1.772 second using v1.01-cache-2.11-cpan-39bf76dae61 )