======================================================================
 HTTP::Handy PSGI চিট শিট                             [BN] বাংলা
======================================================================

[ 1. সার্ভার শুরু করা ]

  use HTTP::Handy;

  my $app = sub {
      my $env = shift;
      return [200, ['Content-Type', 'text/plain'], ['Hello']];
  };

  HTTP::Handy->run(
      app           => $app,       # বাধ্যতামূলক: PSGI app code reference
      host          => '127.0.0.1',# ঐচ্ছিক: bind address (default: 0.0.0.0)
      port          => 8080,       # ঐচ্ছিক: port (default: 8080)
      log           => 1,          # ঐচ্ছিক: access log (default: 1)
      max_post_size => 10485760,   # ঐচ্ছিক: max POST bytes (default: 10MB)
  );

  perl lib/HTTP/Handy.pm [port]

[ 2. অনুরোধ পরিবেশ চলক ($env) ]

  REQUEST_METHOD    স্ট্রিং  "GET" / "POST"
  PATH_INFO         স্ট্রিং  /index.html
  QUERY_STRING      স্ট্রিং  key=val
  SERVER_NAME       স্ট্রিং  hostname
  SERVER_PORT       পূর্ণসংখ্যা  8080
  CONTENT_TYPE      স্ট্রিং  content-type
  CONTENT_LENGTH    পূর্ণসংখ্যা  (bytes)
  HTTP_*            স্ট্রিং  HTTP_USER_AGENT ...
  psgi.input        অবজেক্ট  (POST body)
  psgi.errors       glob  \*STDERR
  psgi.url_scheme   স্ট্রিং  "http"

[ 3. প্রতিক্রিয়া ফরম্যাট ]

  [$status, \@headers, \@body]

  [200, ['Content-Type', 'text/plain'], ['OK']]
  [404, ['Content-Type', 'text/plain'], ['Not Found']]
  [302, ['Location', '/new'], ['']]
  [204, ['Content-Length', '0'], []]

[ 4. POST বডি পড়া (psgi.input) ]

  my $body = '';
  my $len  = $env->{CONTENT_LENGTH} || 0;
  $env->{'psgi.input'}->read($body, $len) if $len > 0;

  read($buf,$len)   read($buf,$len,$off)
  seek($pos,$wh)    tell()
  getline()         getlines()

[ 5. ইউটিলিটি পদ্ধতি ]

  HTTP::Handy->parse_query($env->{QUERY_STRING})  ->  %hash
  HTTP::Handy->parse_query($post_body)             ->  %hash
  HTTP::Handy->url_decode('hello%20world')         ->  "hello world"
  HTTP::Handy->mime_type('css')                    ->  "text/css"
  HTTP::Handy->is_htmx($env)                       ->  1 / 0

[ 6. প্রতিক্রিয়া নির্মাণ পদ্ধতি ]

  response_html($html [,$code])    text/html; charset=utf-8
  response_text($text [,$code])    text/plain; charset=utf-8
  response_json($json [,$code])    application/json
  response_redirect($url [,$code]) Location: $url

[ 7. স্থির ফাইল পরিবেশন ]

  return HTTP::Handy->serve_static($env, './htdocs');
  return HTTP::Handy->serve_static($env, './htdocs',
      cache_max_age => 3600);

[ 8. রাউটিং প্যাটার্ন ]

  my $method = $env->{REQUEST_METHOD};
  my $path   = $env->{PATH_INFO};

  if ($method eq 'GET'  && $path eq '/') { ... }
  if ($method eq 'POST' && $path eq '/x') { ... }
  if ($path =~ m{^/api/}) { ... }
  if ($path =~ m{^/user/(\d+)$}) { my $id=$1; ... }

[ 9. ত্রুটি পরিচালনা ]

  die "msg"  ->  500 স্বয়ংক্রিয় 500 প্রতিক্রিয়া
  [500, ['Content-Type','text/plain'], ['error']]
  [403, ['Content-Type','text/plain'], ['forbidden']]
  [400, ['Content-Type','text/plain'], ['bad request']]

[ 10. run() দ্বারা তৈরি লগ ফাইল ]

  logs/access/YYYYMMDDHHm0.log.ltsv  অ্যাক্সেস লগ (10 মিনিট রোটেশন, LTSV)
  logs/error/error.log                ত্রুটি/স্টার্টআপ লগ

  LTSV: time  method  path  status  size  ua  referer

[ 11. অফিসিয়াল রিসোর্স ]

  PSGI specification:
    https://github.com/plack/psgi-specs/blob/master/PSGI.pod
  PSGI (MetaCPAN): https://metacpan.org/pod/PSGI
  Plack: https://plackperl.org/
  HTTP::Handy: https://metacpan.org/dist/HTTP-Handy

======================================================================
