code: private void putObject(WebContext ctx, Bucket bucket, String id, InputStreamHandler inputStream)
              throws IOException {
          StoredObject object = bucket.getObject(id);
          if (inputStream == null) {
              signalObjectError(ctx, HttpResponseStatus.BAD_REQUEST, "No content posted");
              return;
          }
          try (FileOutputStream out = new FileOutputStream(object.getFile())) {
              ByteStreams.copy(inputStream, out);
          }
  
          Map<String, String> properties = Maps.newTreeMap();
          for (String name : ctx.getRequest().headers().names()) {
              String nameLower = name.toLowerCase();
              if (nameLower.startsWith("x-amz-meta-") || "content-md5".equals(nameLower) || "content-type".equals(
                      nameLower) || "x-amz-acl".equals(nameLower)) {
                  properties.put(name, ctx.getHeader(name));
              }
          }
  
          HashCode hash = Files.hash(object.getFile(), Hashing.md5());
          String md5 = BaseEncoding.base64().encode(hash.asBytes());
          String contentMd5 = properties.get("Content-MD5");
          if (properties.containsKey("Content-MD5") && !md5.equals(contentMd5)) {
              object.delete();
              signalObjectError(ctx,
                                HttpResponseStatus.BAD_REQUEST,
                                Strings.apply("Invalid MD5 checksum (Input: %s, Expected: %s)", contentMd5, md5));
              return;
          }
  
          String etag = BaseEncoding.base16().encode(hash.asBytes());
          properties.put(HTTP_HEADER_NAME_ETAG, etag);
          object.storeProperties(properties);
          Response response = ctx.respondWith();
          response.addHeader(HTTP_HEADER_NAME_ETAG, etag(etag)).status(HttpResponseStatus.OK);
          response.addHeader(HttpHeaderNames.ACCESS_CONTROL_EXPOSE_HEADERS, HTTP_HEADER_NAME_ETAG);
          signalObjectSuccess(ctx);
      }
docs: Handles PUT /bucket/id
  
  @param ctx    the context describing the current request
  @param bucket the bucket containing the object to upload
  @param id     name of the object to upload