[
  {
    "path": ".dockerignore",
    "content": "*\n!Dockerfile\n!files/*\n"
  },
  {
    "path": ".gitignore",
    "content": ".env\n.DS_Store\nlocustfile.pyc\nuser-data\n.vagrant\n"
  },
  {
    "path": ".travis.yml",
    "content": "sudo: required\nservices:\n- docker\nscript:\n- docker -v\n- docker build -t quay.io/wantedly/nginx-image-server .\n- script/run -d\n- script/run-infrataster\nnotifications:\n  slack:\n    secure: C5l4fgeuirkGPI4BYZP1onHY1FbYbth5UuGRZzmJ/6OBMdwV4HdHl7Gbt92NiD+7EhtWOh1qtqgFPakoVZjrrva3vS/cR1drvh80qQbF/OjZRsR68p0kjJDEn5uJf66iP0DBkFRWYliE0CILXha6T/5xxOQthuoI7OWfrI8SQi0=\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM ubuntu:14.04\n\nENV NGINX_VERSION 1.10.0\nENV NGX_SMALL_LIGHT_VERSION 0.9.1\nENV IMAGEMAGICK_VERSION 6.8.6-8\n\n# Install dependency packages\nRUN apt-get update && \\\n    apt-get install -y \\\n      binutils-doc \\\n      bison \\\n      flex \\\n      g++ \\\n      gettext \\\n      libpcre3 \\\n      libpcre3-dev \\\n      libssl-dev \\\n      libperl-dev \\\n      make && \\\n    rm -rf /var/lib/apt/lists/*\n\n# Build ImageMagick with WebP support\nRUN mkdir -p /tmp/imagemagick && \\\n    cd /tmp/imagemagick && \\\n    echo \"\\ndeb-src http://archive.ubuntu.com/ubuntu/ trusty main restricted\" >> /etc/apt/sources.list && \\\n    apt-get update && \\\n    apt-get build-dep -y imagemagick && \\\n    apt-get install -y libwebp-dev devscripts checkinstall && \\\n    curl -L https://launchpad.net/imagemagick/main/${IMAGEMAGICK_VERSION}/+download/ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz > \\\n      ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz && \\\n    tar zxf ImageMagick-${IMAGEMAGICK_VERSION}.tar.gz && \\\n    cd ImageMagick-${IMAGEMAGICK_VERSION} && \\\n    ./configure \\\n      --prefix=/usr \\\n      --sysconfdir=/etc \\\n      --libdir=/usr/lib/x86_64-linux-gnu \\\n      --enable-shared \\\n      --with-modules \\\n      --disable-openmp \\\n      --with-webp=yes \\\n      LDFLAGS=-L/usr/local/lib \\\n      CPPFLAGS=-I/usr/local/include && \\\n    make && \\\n    checkinstall -y && \\\n    rm -rf /tmp/imagemagick && \\\n    rm -rf /var/lib/apt/lists/*\n\n# Fetch and unarchive nginx source\nRUN curl -L http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz > /tmp/nginx-${NGINX_VERSION}.tar.gz && \\\n    cd /tmp && \\\n    tar zxf nginx-${NGINX_VERSION}.tar.gz\n\n# Fetch and unarchive ngx_small_light module\nRUN curl -L https://github.com/cubicdaiya/ngx_small_light/archive/v${NGX_SMALL_LIGHT_VERSION}.tar.gz > /tmp/ngx_small_light-${NGX_SMALL_LIGHT_VERSION}.tar.gz && \\\n    cd /tmp && \\\n    tar zxf ngx_small_light-${NGX_SMALL_LIGHT_VERSION}.tar.gz && \\\n    cd /tmp/ngx_small_light-${NGX_SMALL_LIGHT_VERSION} && \\\n    ./setup\n\n# Compile nginx\nRUN cd /tmp/nginx-${NGINX_VERSION} && \\\n    ./configure \\\n      --prefix=/opt/nginx \\\n      --conf-path=/etc/nginx/nginx.conf \\\n      --sbin-path=/opt/nginx/sbin/nginx \\\n      --with-http_stub_status_module \\\n      --with-http_perl_module \\\n      --with-pcre \\\n      --add-module=/tmp/ngx_small_light-${NGX_SMALL_LIGHT_VERSION} && \\\n    make && \\\n    make install && \\\n    rm -rf /tmp/*\n\nRUN mkdir -p /etc/nginx && \\\n    mkdir -p /opt/nginx/perl/lib && \\\n    mkdir -p /var/run && \\\n    mkdir -p /etc/nginx/conf.d && \\\n    mkdir -p /var/www/nginx/cache && \\\n    mkdir -p /var/www/nginx/images && \\\n    mkdir -p /var/www/nginx/tmp\n\n# Add config files\nCOPY files/nginx.conf   /etc/nginx/nginx.conf\nCOPY files/mime.types   /etc/nginx/mime.types\nCOPY files/validator.pm /opt/nginx/perl/lib/validator.pm\n\nEXPOSE 80 8090\n\nCMD [\"/opt/nginx/sbin/nginx\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2014-2016 Wantedly, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Nginx Image Server\n[![Docker Repository on Quay.io](https://quay.io/repository/wantedly/nginx-image-server/status \"Docker Repository on Quay.io\")](https://quay.io/repository/wantedly/nginx-image-server)\n[![Build Status](https://travis-ci.org/wantedly/nginx-image-server.svg)](https://travis-ci.org/wantedly/nginx-image-server)\n\nDocker Image for [Nginx](http://nginx.org/) server for image processing with [ngx_small_light](https://github.com/cubicdaiya/ngx_small_light).\nIt supports resizing/cropping/formatting (`png`, `webp`...etc) of images stored in local storages or AWS S3.\n\nPlease see https://github.com/cubicdaiya/ngx_small_light for more information about image processing.\n\n## SUPPORTED TAGS\n\n* `latest`\n  * Nginx 1.10.0\n  * ngx_small_light 0.9.1\n  * ImageMagick 6.8.6-8 (Q16) with WebP support\n\n## HOW TO USE\n\n```bash\n# Get the docker image\n$ docker pull quay.io/wantedly/nginx-image-server\n\n# Fetch an example image to try image-processing local image\n$ curl -L https://raw.githubusercontent.com/wantedly/nginx-image-server/master/examples/example.jpg > \\\n    /tmp/example.jpg\n\n# Start the image server\n$ docker run \\\n    --rm \\\n    -it \\\n    --name nginx-image-server \\\n    -p 80:80 \\\n    -p 8090:8090 \\\n    -v /tmp/example.jpg:/var/www/nginx/images/example.jpg \\\n    -e \"SERVER_NAME=image.example.com\" \\\n    -e \"S3_HOST=<YOUR-BUCKET-NAME>.s3.amazonaws.com\" \\\n    quay.io/wantedly/nginx-image-server:latest\n```\n\nThen you can try image-processing by accessing\n\n* **Images in S3**: `http://<YOUR-SERVER.com>/small_light(dh=400,da=l,ds=s)/<PATH-TO-IMAGE-IN-S3>`\n* **Images in Local**: `http://<YOUR-SERVER.com>/local/small_light(dh=400,da=l,ds=s)/images/example.jpg`\n\nAnd `http://<YOUR-SERVER.com>:8090/status` retruns the nginx status.\n\n### Custom configuration\nYou can build a docker image includes your own `nginx.conf`:\n\n```\nFROM quay.io/wantedly/nginx-image-server\nCOPY nginx.conf /etc/nginx/nginx.conf\n```\n\nThen build with `docker build -t your-nginx-image-server .` and run:\n\n```bash\n$ docker run \\\n    -d \\\n    --name your-nginx-image-server \\\n    -p 80:80 \\\n    your-nginx-image-server\n```\n\nBe sure to include `daemon off;` in your custom configuration to run Nginx in the foreground.\nOtherwise your container will stop immediately after starting.\n\n## HOW TO DEVELOP\n\n```bash\n# on your local machine\n$ git clone https://github.com/wantedly/nginx-image-server.git && cd nginx-image-server\n$ script/bootstrap\n$ cp .env.sample .env\n```\n\n```\n# .env\nTIMEZONE=Asia/Tokyo\n```\n\n```\n$ vagrant up\n$ vi Dockerfile\n\n# login to VM and test it\n$ vagrant ssh\n@core-01 $ cd share\n@core-01 $ docker build -t=quay.io/wantedly/nginx-image-server .\n@core-01 $ script/test\n```\n\n\n## TEST\n[![wercker status](https://app.wercker.com/status/e1d50221515bacea622f6a6f5f0adde6/s/master \"wercker status\")](https://app.wercker.com/project/bykey/e1d50221515bacea622f6a6f5f0adde6)\n\n### Feature(behavior) test\nBehavior test with [infrataster](https://github.com/ryotarai/infrataster).\nTest files are under `test/feature` directory. You can run this test with follwing script:\n\n```bash\n$ script/test\n```\n\n### Performance test\nPerformance test with [locust](http://locust.io/).\nTest files are under `test/performance` directory. You can run locust with follwing script:\n\n```bash\n# Run target container\n$ script/run\n\n# Export target IP\n$ export TARGET_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' nginx-image-server)\n\n# Run locust as WebTool\n$ script/run-locust -f locustfile.py -H http://${TARGET_IP}\n\n# Run locust as CLI\n$ script/run-locust -f locustfile.py -H http://${TARGET_IP} --no-web -c 5 -r 1 -n 10\n```\n\n## LICENSE\n[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg?style=flat)](LICENSE)\n"
  },
  {
    "path": "coreos/Vagrantfile",
    "content": "# -*- mode: ruby -*-\n# # vi: set ft=ruby :\n\nrequire 'fileutils'\n\nVagrant.require_version \">= 1.6.0\"\n\nCLOUD_CONFIG_PATH = File.join(File.dirname(__FILE__), \"user-data\")\nCONFIG = File.join(File.dirname(__FILE__), \"config.rb\")\n\n# Defaults for config options defined in CONFIG\n$num_instances = 1\n$update_channel = \"alpha\"\n$enable_serial_logging = false\n$vb_gui = false\n$vb_memory = 1024\n$vb_cpus = 1\n\n# Attempt to apply the deprecated environment variable NUM_INSTANCES to\n# $num_instances while allowing config.rb to override it\nif ENV[\"NUM_INSTANCES\"].to_i > 0 && ENV[\"NUM_INSTANCES\"]\n  $num_instances = ENV[\"NUM_INSTANCES\"].to_i\nend\n\nif File.exist?(CONFIG)\n  require CONFIG\nend\n\nVagrant.configure(\"2\") do |config|\n  # always use Vagrants insecure key\n  config.ssh.insert_key = false\n\n  config.vm.box = \"coreos-%s\" % $update_channel\n  config.vm.box_version = \">= 308.0.1\"\n  config.vm.box_url = \"http://%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant.json\" % $update_channel\n\n  config.vm.provider :vmware_fusion do |vb, override|\n    override.vm.box_url = \"http://%s.release.core-os.net/amd64-usr/current/coreos_production_vagrant_vmware_fusion.json\" % $update_channel\n  end\n\n  config.vm.provider :virtualbox do |v|\n    # On VirtualBox, we don't have guest additions or a functional vboxsf\n    # in CoreOS, so tell Vagrant that so it can be smarter.\n    v.check_guest_additions = false\n    v.functional_vboxsf     = false\n  end\n\n  # plugin conflict\n  if Vagrant.has_plugin?(\"vagrant-vbguest\") then\n    config.vbguest.auto_update = false\n  end\n\n  (1..$num_instances).each do |i|\n    config.vm.define vm_name = \"core-%02d\" % i do |config|\n      config.vm.hostname = vm_name\n\n      if $enable_serial_logging\n        logdir = File.join(File.dirname(__FILE__), \"log\")\n        FileUtils.mkdir_p(logdir)\n\n        serialFile = File.join(logdir, \"%s-serial.txt\" % vm_name)\n        FileUtils.touch(serialFile)\n\n        config.vm.provider :vmware_fusion do |v, override|\n          v.vmx[\"serial0.present\"] = \"TRUE\"\n          v.vmx[\"serial0.fileType\"] = \"file\"\n          v.vmx[\"serial0.fileName\"] = serialFile\n          v.vmx[\"serial0.tryNoRxLoss\"] = \"FALSE\"\n        end\n\n        config.vm.provider :virtualbox do |vb, override|\n          vb.customize [\"modifyvm\", :id, \"--uart1\", \"0x3F8\", \"4\"]\n          vb.customize [\"modifyvm\", :id, \"--uartmode1\", serialFile]\n        end\n      end\n\n      if $expose_docker_tcp\n        config.vm.network \"forwarded_port\", guest: 2375, host: ($expose_docker_tcp + i - 1), auto_correct: true\n      end\n\n      config.vm.provider :vmware_fusion do |vb|\n        vb.gui = $vb_gui\n      end\n\n      config.vm.provider :virtualbox do |vb|\n        vb.gui = $vb_gui\n        vb.memory = $vb_memory\n        vb.cpus = $vb_cpus\n      end\n\n      ip = \"172.17.8.#{i+100}\"\n      config.vm.network :private_network, ip: ip\n\n      # Uncomment below to enable NFS for sharing the host machine into the coreos-vagrant VM.\n      config.vm.synced_folder \"../\", \"/home/core/share\", id: \"core\", :nfs => true, :mount_options => ['nolock,vers=3,udp']\n\n      if File.exist?(CLOUD_CONFIG_PATH)\n        config.vm.provision :file, :source => \"#{CLOUD_CONFIG_PATH}\", :destination => \"/tmp/vagrantfile-user-data\"\n        config.vm.provision :shell, :inline => \"mv /tmp/vagrantfile-user-data /var/lib/coreos-vagrant/\", :privileged => true\n      end\n\n    end\n  end\nend\n"
  },
  {
    "path": "coreos/config.rb",
    "content": "require 'erb'\nrequire 'dotenv'\n\n# Create user-data from erb template\nDotenv.load\nerb = File.open(File.join(File.dirname(__FILE__), \"user-data.yml.erb\")) { |f| ERB.new(f.read) }\nFile.write(File.join(File.dirname(__FILE__), \"user-data\"), erb.result(binding))\n\n# To automatically replace the discovery token on 'vagrant up', uncomment\n# the lines below:\n#\n#if File.exists?('user-data') && ARGV[0].eql?('up')\n#  require 'open-uri'\n#  require 'yaml'\n#\n#  token = open('https://discovery.etcd.io/new').read\n#\n#  data = YAML.load(IO.readlines('user-data')[1..-1].join)\n#  data['coreos']['etcd']['discovery'] = token\n#\n#  yaml = YAML.dump(data)\n#  File.open('user-data', 'w') { |file| file.write(\"#cloud-config\\n\\n#{yaml}\") }\n#end\n#\n\n#\n# coreos-vagrant is configured through a series of configuration\n# options (global ruby variables) which are detailed below. To modify\n# these options, first copy this file to \"config.rb\". Then simply\n# uncomment the necessary lines, leaving the $, and replace everything\n# after the equals sign..\n\n# Size of the CoreOS cluster created by Vagrant\n$num_instances=1\n\n# Official CoreOS channel from which updates should be downloaded\n$update_channel=\"beta\"\n\n# Log the serial consoles of CoreOS VMs to log/\n# Enable by setting value to true, disable with false\n# WARNING: Serial logging is known to result in extremely high CPU usage with\n# VirtualBox, so should only be used in debugging situations\n#$enable_serial_logging=false\n\n# Enable port forwarding of Docker TCP socket\n# Set to the TCP port you want exposed on the *host* machine, default is 2375\n# If 2375 is used, Vagrant will auto-increment (e.g. in the case of $num_instances > 1)\n# You can then use the docker tool locally by setting the following env var:\n#   export DOCKER_HOST='tcp://127.0.0.1:2375'\n#$expose_docker_tcp=2375\n\n# Setting for VirtualBox VMs\n#$vb_gui = false\n#$vb_memory = 1024\n#$vb_cpus = 1\n"
  },
  {
    "path": "coreos/user-data.yml.erb",
    "content": "#cloud-config\n\ncoreos:\n  update:\n    group: beta\n    reboot-strategy: off\n  units:\n    - name: settimezone.service\n      command: start\n      content: |\n        [Unit]\n        Description=Set the timezone\n\n        [Service]\n        ExecStart=/usr/bin/timedatectl set-timezone <%= ENV[\"TIMEZONE\"] %>\n        RemainAfterExit=yes\n        Type=oneshot\n    - name: docker-tcp.socket\n      command: start\n      enable: true\n      content: |\n        [Unit]\n        Description=Docker Socket for the API\n\n        [Socket]\n        ListenStream=2375\n        Service=docker.service\n        BindIPv6Only=both\n\n        [Install]\n        WantedBy=sockets.target\nwrite_files:\n  - path: /etc/ssh/sshd_config\n    permissions: 0600\n    owner: root:root\n    content: |\n      # Use most defaults for sshd configuration.\n      UsePrivilegeSeparation sandbox\n      Subsystem sftp internal-sftp\n\n      PermitRootLogin no\n      PasswordAuthentication no\n      ChallengeResponseAuthentication no\n  - path: /etc/ntp.conf\n    content: |\n      # Common pool\n      server 0.pool.ntp.org\n      server 1.pool.ntp.org\n      server 2.pool.ntp.org\n      server 3.pool.ntp.org\n\n      # - Allow only time queries, at a limited rate.\n      # - Allow all local queries (IPv4, IPv6)\n      restrict default nomodify nopeer noquery limited kod\n      restrict 127.0.0.1\n      restrict [::1]\n"
  },
  {
    "path": "files/mime.types",
    "content": "types {\n    text/html                             html htm shtml;\n    text/css                              css;\n    text/xml                              xml;\n    image/gif                             gif;\n    image/jpeg                            jpeg jpg;\n    application/javascript                js;\n    application/json                      json;\n    application/atom+xml                  atom;\n    application/rss+xml                   rss;\n    text/mathml                           mml;\n    text/plain                            txt;\n    text/vnd.sun.j2me.app-descriptor      jad;\n    text/vnd.wap.wml                      wml;\n    text/x-component                      htc;\n    image/png                             png;\n    image/tiff                            tif tiff;\n    image/vnd.wap.wbmp                    wbmp;\n    image/x-icon                          ico;\n    image/x-jng                           jng;\n    image/x-ms-bmp                        bmp;\n    image/svg+xml                         svg svgz;\n    image/webp                            webp;\n    application/java-archive              jar war ear;\n    application/mac-binhex40              hqx;\n    application/msword                    doc;\n    application/pdf                       pdf;\n    application/postscript                ps eps ai;\n    application/rtf                       rtf;\n    application/vnd.ms-excel              xls;\n    application/vnd.ms-powerpoint         ppt;\n    application/vnd.wap.wmlc              wmlc;\n    application/vnd.google-earth.kml+xml  kml;\n    application/vnd.google-earth.kmz      kmz;\n    application/x-7z-compressed           7z;\n    application/x-cocoa                   cco;\n    application/x-java-archive-diff       jardiff;\n    application/x-java-jnlp-file          jnlp;\n    application/x-makeself                run;\n    application/x-perl                    pl pm;\n    application/x-pilot                   prc pdb;\n    application/x-rar-compressed          rar;\n    application/x-redhat-package-manager  rpm;\n    application/x-sea                     sea;\n    application/x-shockwave-flash         swf;\n    application/x-stuffit                 sit;\n    application/x-tcl                     tcl tk;\n    application/x-x509-ca-cert            der pem crt;\n    application/x-xpinstall               xpi;\n    application/xhtml+xml                 xhtml;\n    application/zip                       zip;\n    application/octet-stream              bin exe dll;\n    application/octet-stream              deb;\n    application/octet-stream              dmg;\n    application/octet-stream              eot;\n    application/octet-stream              iso img;\n    application/octet-stream              msi msp msm;\n    audio/midi                            mid midi kar;\n    audio/mpeg                            mp3;\n    audio/ogg                             ogg;\n    audio/x-m4a                           m4a;\n    audio/x-realaudio                     ra;\n    video/3gpp                            3gpp 3gp;\n    video/mp4                             mp4;\n    video/mpeg                            mpeg mpg;\n    video/quicktime                       mov;\n    video/webm                            webm;\n    video/x-flv                           flv;\n    video/x-m4v                           m4v;\n    video/x-mng                           mng;\n    video/x-ms-asf                        asx asf;\n    video/x-ms-wmv                        wmv;\n    video/x-msvideo                       avi;\n}\n"
  },
  {
    "path": "files/nginx.conf",
    "content": "env SERVER_NAME;\nenv S3_HOST;\n\nuser root;\nworker_processes 4;\ndaemon off;\n#worker_rlimit_nofile\nerror_log /dev/stdout info;\npid /var/run/nginx.pid;\n\nevents {\n    worker_connections 1024;\n    #multi_accept on;\n    #use\n}\n\nhttp {\n    perl_modules perl/lib;\n    perl_require validator.pm;\n\n    perl_set $server_name_from_env 'sub { return $ENV{\"SERVER_NAME\"}; }';\n    perl_set $s3_host_from_env 'sub { return $ENV{\"S3_HOST\"}; }';\n\n    include /etc/nginx/mime.types;\n    default_type application/octet-stream;\n\n    #access_log off;\n    access_log /dev/stdout;\n    server_tokens off;\n\n    sendfile on;\n    tcp_nopush on;\n    tcp_nodelay on;\n\n    keepalive_timeout 65;\n\n    gzip on;\n    gzip_http_version 1.0;\n    gzip_comp_level 2;\n    gzip_proxied any;\n    gzip_vary off;\n    #gzip_buffers\n    gzip_types text/plain text/css application/x-javascript text/xml application/xml application/rss+xml application/atom+xml text/javascript application/javascript application/json text/mathml;\n    gzip_min_length  1000;\n    gzip_disable     MSIE [1-6]\\.;\n\n    server_names_hash_bucket_size 64;\n    types_hash_max_size 2048;\n    types_hash_bucket_size 64;\n    #proxy_read_timeout\n    #client_body_buffer_size\n    #client_max_body_size\n\n    limit_req_zone $binary_remote_addr zone=default:10m rate=1r/s;\n\n    proxy_cache_path /var/www/nginx/cache levels=1:2 keys_zone=cache-space:4m max_size=50m inactive=120m;\n    proxy_temp_path /var/www/nginx/tmp;\n\n    server {\n      listen 80;\n      server_name $server_name_from_env;\n\n      location ~ ^/(.+)$ {\n        proxy_pass http://localhost:8080;\n        proxy_cache cache-space;\n        proxy_cache_valid 200 60m;\n      }\n    }\n\n    server {\n      listen 8080;\n      server_name $server_name_from_env;\n      resolver 8.8.8.8;\n      small_light on;\n\n      location @empty {\n        empty_gif;\n      }\n\n      location /favicon.ico {\n        empty_gif;\n        access_log    off;\n        log_not_found off;\n      }\n\n      # Image processing for images in local file\n      location ~ ^/local/small_light[^/]*/(.+)$ {\n        set $small_light_maximum_size 3072;\n        perl validator::handler;\n      }\n\n      # Image processing for images in AWS S3\n      location ~ ^/small_light[^/]*/(.+)$ {\n        set $small_light_maximum_size 3072;\n        perl validator::handler;\n      }\n\n      location ~ ^/images/(.+)$ {\n        root /var/www/nginx;\n        error_page 415 = @empty;\n      }\n\n      location ~ ^/(.+)$ {\n        proxy_pass http://$s3_host_from_env/$1;\n        error_page 415 = @empty;\n      }\n    }\n\n    server {\n      listen 8090;\n      server_name $server_name_from_env;\n\n      location /status {\n        stub_status on;\n        access_log off;\n      }\n    }\n\n    include /etc/nginx/conf.d/*.conf;\n}\n"
  },
  {
    "path": "files/validator.pm",
    "content": "package validator;\n\nuse nginx;\nuse strict;\nuse warnings;\n\nsub handler {\n  my $r = shift;\n  my $uri = \"/\" . ($r->uri =~ /^.*\\/small_light[^\\/]*\\/(.+)$/m)[0];\n  my $threshold = $r->variable(\"small_light_maximum_size\");\n\n  unless ($threshold) {\n    $r->log_error(100, \"small_light_maximum_size is not defined!\");\n    $r->internal_redirect($uri);\n\n    return OK;\n  }\n\n  my $bad_request = 0;\n  my @params = $r->uri =~ /([a-zA-Z]+=[0-9a-zA-Z]+),?/g;\n\n  foreach my $param (@params) {\n    my ($key, $value) = split(\"=\", $param);\n\n    if (grep(/^${key}$/, (\"cw\", \"dw\", \"ch\", \"dh\"))) {\n      if ($value > $threshold) {\n        $r->log_error(100, \"Invalid resize parameter, \" . $key . \": \" . $value);\n        $bad_request = 1;\n        last;\n      }\n    }\n  }\n\n  if ($bad_request) {\n    # to avoid ngx_small_light process and return 400\n    $r->send_http_header;\n\n    return HTTP_BAD_REQUEST;\n  }\n\n  $r->internal_redirect($uri);\n\n  return OK;\n}\n\n1;\n__END__\n"
  },
  {
    "path": "script/bootstrap",
    "content": "#!/bin/bash\n#\n# bootstrap\n#\n# Get readly to develop\n\nset -e\n\n#\n# Welcome message\n#\necho \"\"\necho \"  nginx-image-server\"\necho \"\"\n\n#\n# Check for VirtualBox\n#\nif test ! $(which virtualbox)\nthen\n  echo \"  x You need to install VirtualBox.\"\n  echo \"    You can download it from https://www.virtualbox.org/wiki/Downloads\"\n  exit 1\nelse\n  echo \"  + VirtualBox found.\"\nfi\n\n#\n# Check for Vagrant\n#\nif test ! $(which vagrant)\nthen\n  echo \"  x You need to install Vagrant.\"\n  echo \"    You can download it from http://www.vagrantup.com/downloads.html\"\n  exit 1\nelse\n  echo \"  + Vagrant found.\"\nfi\n\n#\n# Install vagrant plugin\n#\nif [[ $(vagrant plugin list) =~ dotenv ]]\nthen\n  echo \"  + Vagrant plugin 'dotenv' found.\"\nelse\n  echo \"  x You need to install Vagrant plugin 'dotenv':\"\n  echo \"    $ vagrant plugin install dotenv\"\n  exit 1\nfi\n\n#\n# Startup instructions\n#\necho \"\"\necho \"  Good work. We're ready.\"\n\nexit 0\n"
  },
  {
    "path": "script/build",
    "content": "#!/bin/bash\n#\n# Usage: script/build\n# Description: build nginx-image-server\n#\n\nset -e\n\ndocker build -t=quay.io/wantedly/nginx-image-server .\n"
  },
  {
    "path": "script/run",
    "content": "#!/bin/bash\n#\n# Usage: script/run <MODE>\n# Description: run nginx-image-server container\n# Example:\n#   $ script/run-target\n#   $ script/run-target -d\n#\n\nBASE_DIRECTORY=`pwd`\nMODE=\"--rm -it\"\n\nif [ $# -eq 1 ]; then\n  if [ $1 = \"-d\" ]; then\n    MODE=\"-d\"\n  fi\nfi\n\ncd ${BASE_DIRECTORY}\ndocker kill target > /dev/null 2>&1 || true\ndocker rm   target > /dev/null 2>&1 || true\ndocker run \\\n  ${MODE} \\\n  --name nginx-image-server \\\n  -p 80:80 \\\n  -p 8090:8090 \\\n  -v ${BASE_DIRECTORY}/examples:/var/www/nginx/images/ \\\n  -e \"SERVER_NAME=${SERVER_NAME}\" \\\n  -e \"S3_HOST=${S3_HOST}\" \\\n  quay.io/wantedly/nginx-image-server:latest\n"
  },
  {
    "path": "script/run-infrataster",
    "content": "#!/bin/bash\n#\n# Usage: script/run-infrataster\n# Description: run infrataster container\n#\n\nBASE_DIRECTORY=`pwd`\n\ncd ${BASE_DIRECTORY}/test/feature\ndocker kill tester > /dev/null 2>&1 || true\ndocker rm   tester > /dev/null 2>&1 || true\ndocker run \\\n  --rm \\\n  --name infrataster \\\n  -v $PWD/spec:/test/spec \\\n  -e TARGET_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' nginx-image-server) \\\n  quay.io/wantedly/infrataster:latest\n"
  },
  {
    "path": "script/run-locust",
    "content": "#!/bin/bash\n#\n# Usage: script/run-locust <LOCUST_ARGS>\n# Description: run tester container\n# Example:\n#   script/run-locust -f locustfile.py -H localhost --no-web -c 10 -r 1 -n 30\n#   script/run-locust -f locustfile.py -H localhost\n#\n\nBASE_DIRECTORY=`pwd`\nLOCUST_ARGS=$@\n\ncd ${BASE_DIRECTORY}/test/performance\ndocker kill locust > /dev/null 2>&1 || true\ndocker rm   locust > /dev/null 2>&1 || true\ndocker run \\\n  --rm \\\n  -it \\\n  --name locust \\\n  -p 8089:8089 \\\n  -v ${BASE_DIRECTORY}/test/performance:/test \\\n  quay.io/wantedly/locust:latest \\\n  ${LOCUST_ARGS}\n"
  },
  {
    "path": "script/test",
    "content": "#!/bin/sh\n#\n# Usage: script/cibuild\n# Description: script to run test\n#\n\nset -e\n\n# this script should be run in project root\nBASE_DIRECTORY=`pwd`\nSERVER_NAME=\"image.example.com\"\n\necho \"==> Building target...\"\ncd ${BASE_DIRECTORY}\nscript/build\n\necho \"==> Running nginx-image-server...\"\ndocker kill nginx-image-server > /dev/null 2>&1 || true\ndocker rm   nginx-image-server > /dev/null 2>&1 || true\ndocker kill infrataster > /dev/null 2>&1 || true\ndocker rm   infrataster > /dev/null 2>&1 || true\nscript/run -d\n\necho \"==> Running test...\"\nscript/run-infrataster\n\necho \"==> Cleaning up...\"\ndocker kill nginx-image-server > /dev/null 2>&1 || true\ndocker rm   nginx-image-server > /dev/null 2>&1 || true\ndocker kill infrataster > /dev/null 2>&1 || true\ndocker rm   infrataster > /dev/null 2>&1 || true\n"
  },
  {
    "path": "test/feature/spec/nginx_image_server_spec.rb",
    "content": "require \"spec_helper\"\n\ndescribe server(:target) do\n  describe http('http://target/images/example.jpg') do\n    it \"responds OK 200\" do\n      expect(response.status).to eq(200)\n    end\n    it \"responds as 'image/jpeg'\" do\n      expect(response.headers['content-type']).to eq(\"image/jpeg\")\n    end\n  end\n\n  describe http('http://target/local/small_light(dh=600,da=l,ds=s,of=png)/images/example.jpg') do\n    it \"responds OK 200\" do\n      expect(response.status).to eq(200)\n    end\n    it \"responds as 'image/png'\" do\n      expect(response.headers['content-type']).to eq(\"image/png\")\n    end\n  end\n\n  describe http('http://target/local/small_light(dh=600,da=l,ds=s,of=webp)/images/example.jpg') do\n    it \"responds OK 200\" do\n      expect(response.status).to eq(200)\n    end\n    it \"responds as 'image/webp'\" do\n      expect(response.headers['content-type']).to eq(\"image/webp\")\n    end\n  end\n\n  describe http('http://target:8090/status') do\n    it \"responds OK 200\" do\n      expect(response.status).to eq(200)\n    end\n    it \"responds content including 'Active connections'\" do\n      expect(response.body).to include(\"Active connections\")\n    end\n  end\n\n  describe http('http://target/local/small_light(dh=3600,da=l,ds=s,of=webp)/images/example.jpg') do\n    it \"responds Bad Request 400\" do\n      expect(response.status).to eq(400)\n    end\n  end\n\n  describe http('http://target/local/small_light(ch=3600,da=l,ds=s,of=webp)/images/example.jpg') do\n    it \"responds Bad Request 400\" do\n      expect(response.status).to eq(400)\n    end\n  end\n\n  describe http('http://target/local/small_light(dw=3600,da=l,ds=s,of=webp)/images/example.jpg') do\n    it \"responds Bad Request 400\" do\n      expect(response.status).to eq(400)\n    end\n  end\n\n  describe http('http://target/local/small_light(cw=3600,da=l,ds=s,of=webp)/images/example.jpg') do\n    it \"responds Bad Request 400\" do\n      expect(response.status).to eq(400)\n    end\n  end\nend\n"
  },
  {
    "path": "test/feature/spec/spec_helper.rb",
    "content": "require \"infrataster/rspec\"\n\nInfrataster::Server.define(\n  :target,\n  ENV[\"TARGET_IP\"],\n  vagrant: false,\n)\n"
  },
  {
    "path": "test/performance/locustfile.py",
    "content": "from locust import HttpLocust, TaskSet, task\nimport random\n\nclass MyTaskSet(TaskSet):\n    @task\n    def index(self):\n      dh = random.randint(1, 1200)\n      of = random.choice([\"jpg\", \"gif\", \"png\", \"webp\"])\n      self.client.get(\"/local/small_light(dh=\" + str(dh) + \",da=l,ds=s,cc=FFFFFF,of=\" + of + \")/images/example.jpg\")\n\nclass WebsiteUser(HttpLocust):\n    task_set = MyTaskSet\n    min_wait=5000\n    max_wait=9000\n"
  },
  {
    "path": "wercker.yml",
    "content": "box: wercker-labs/docker\nbuild:\n  steps:\n    - script:\n        name: Check docker version\n        code: |\n          docker -v\n    - script:\n        name: Build quay.io/wantedly/nginx-image-server\n        code: |\n          cd ${WERCKER_SOURCE_DIR}\n          docker build -t quay.io/wantedly/nginx-image-server .\n    - script:\n        name: Run quay.io/wantedly/nginx-image-server\n        code: >\n          script/run -d\n    - script:\n        name: Run tester\n        code: >\n          script/run-infrataster\n  after-steps:\n    - wantedly/pretty-slack-notify:\n        webhook_url: $SLACK_WEBHOOK_URL\n        channel: $SLACK_CHANNEL\n"
  }
]