=head1 Examples

=head4 Simple example:

=for code

  use v6;

  use Humming-Bird::Core;

  get('/', -> $request, $response {
      $response.html('<h1>Hello World</h1>');
  });

  listen(8080);

  # Navigate to localhost:8080!

=head4 Query params:

=for code

  use v6;

  use Humming-Bird::Core;

  post('/password', -> $request, $response {
      my $super_secret_password = '1234';
      my $password = $request.query('password') || 'Wrong!'; # /password?password=
      if $password eq $super_secret_password {
          $response.html('<h1>That password was correct!</h1>'); # Responses default to 200, change the with .status
      } else {
          $response.status(400).html('<h1>Wrong Password!!!</h1>');
      }
  });

=head4 Simple JSON/path param example:

=for code

  use v6;

  use Humming-Bird::Core;

  my %users = Map.new('bob', '{ "name": "bob" }', 'joe', '{ "name": "joe" }');

  get('/users/:user', -> $request, $response {
      my $user = $request.param('user');

      if %users{$user}:exists {
          $response.json(%users{$user});
      } else {
          $response.status(404);
      }
  });

  listen(8080);

=head4 Example using routers

=for code
  use Humming-Bird::Core;

  my $router = Router.new(root => '/foo/bar');

  # Advice and middleware added will be appended to the routes as they are added.
  $router.middleware(-> $request, $response, &next { $response.header('X-MyHeader', 'True'); &next() });
  $router.advice(-> $response { say $response; $response }); 

  $router.get(-> $request, $response { $response.write('abc') }); # Registers a get route on /foo/bar

  $route.get('/abc', -> $request, $response { $response.write('abc') }); # Registers a get route on /foo/bar/abc

  listen(8080); # No need to register or anything. The router is already registered upon creation.

=head4 Middleware:

=for code

  use v6;

  use Humming-Bird::Core;
  use Humming-Bird::Middleware;

  get('/logged', -> $request, $response {
      $response.html('This request has been logged!');
  }, [ &middleware-logger ]); # &m_logger is provided by Humming-Bird::Middleware

  # Custom middleware
  sub block-firefox($request, $response, &next) {
      return $response.status(400) if $request.header('User-Agent').starts-with('Mozilla');
      $response.status(200);
  }

  get('/no-firefox', -> $request, $response {
      $response.html('You are not using Firefox!');
  }, [ &middleware-logger, &block-firefox ]);

  # Scoped middleware

  # Both of these routes will now share the middleware specified in the last parameter of the group.
  group([
      &get.assuming('/', -> $request, $response {
          $response.write('Index');
      }),

      &post.assuming('/users', -> $request, $response {
          $response.write($request.body).status(204);
      })
  ], [ &middleware-logger, &block-firefox ]);

=head4 Cookies:

=for code
  use v6;

  use Humming-Bird::Core;

  # Middleware to make sure you have an AUTH cookie
  sub authorized($request, $response, &next) {
    without $request.cookie('AUTH') {
      return $response.status(403);
    }

    &next();
  }

  get('/auth/home', -> $request, $response {
    $response.html('You are logged in!');
  }, [ &authorized ]);

  post('/auth/login', -> $request, $response {
    if $request.body eq 'Password123' {
      # TODO: Implement redirects
      $response.cookie('AUTH', 'logged in!', DateTime.now + Duration.new(3600)).html('You logged in!');
    } else {
      $response.status(400);
    }
  });

=head4 Basic CRUD REST API:

=for code
  # A simple REST API using Humming-Bird::Core and JSON::Fast

  use v6;
  use strict;

  use Humming-Bird::Core;
  use Humming-Bird::Middleware;
  use JSON::Marshal;
  use JSON::Unmarshal;

  # Basic model to represent our User
  class User {
      has Str $.name  is required;
      has Int $.age   is required;
      has Str $.email is required;
  }

  # Fake DB, you can pull in DBIish if you need a real DB.
  my @user-database = User.new(name => 'bob', age => 22, email => 'bob@bob.com');

  get('/users', -> $request, $response {
      $response.json(marshal(@user-database));
  }, [ &middleware-logger ]);

  post('/users', -> $request, $response {
      my $user := unmarshal($request.body, User);
      @user-database.push($user);
      $response.json(marshal($user)); # 204 Created
  });

  listen(8080);

=head4 After middleware aka advice

=for code
  use v6.d;
  
  use Humming-Bird::Core;
  use Humming-Bird::Advice;
  
  advice(&advice-logger); # advice-logger is provided by Humming-Bird::Advice.
  
  # Custom advice
  our clicks-today = 0;
  sub update-clicks-today(Response:D $response --> Response:D) {
	clicks-today++;
	$response;
  }
  
  advice(&update-clicks-today); # This will fire after every response is handled.

=head4 Exception/Error handlers

=for code
  use v6.d;

  use Humming-Bird::Core;
  use HTTP::Status;

  # This will catch any X::AdHoc exceptions and use this as the handler
  error(X::AdHoc, -> $exception, $response {
    $response.status(500).write($exception.payload || 'Internal server error.'); # In this case, when we hit an X::AdHoc lets return a 500 with the payload of the exception
  });

=head4 Static files

=for code

  use v6.d;

  use Humming-Bird::Core;

  static('/static', '/var/www/static'); # Will serve static content from /var/www/static on route /static
