95 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
"use strict";
 | 
						|
 | 
						|
var colors = require("colors");
 | 
						|
var cryptoUtil = require("./crypto-util");
 | 
						|
var request = require('request');
 | 
						|
function Acme(privateKey) {
 | 
						|
  this.privateKey = privateKey;
 | 
						|
  this.nonces = [];
 | 
						|
}
 | 
						|
 | 
						|
Acme.prototype.getNonce = function(url, callback) {
 | 
						|
  var req = request.head({
 | 
						|
    url: url,
 | 
						|
  }, function(error, response, body) {
 | 
						|
    if (error) {
 | 
						|
      console.error(error);
 | 
						|
      process.exit(1);
 | 
						|
    }
 | 
						|
    if (response && "replay-nonce" in response.headers) {
 | 
						|
      console.log("Storing nonce: " + response.headers["replay-nonce"]);
 | 
						|
      this.nonces.push(response.headers["replay-nonce"]);
 | 
						|
      callback();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    console.log("Failed to get nonce for request");
 | 
						|
    process.exit(1);
 | 
						|
  }.bind(this));
 | 
						|
}
 | 
						|
 | 
						|
Acme.prototype.post = function(url, body, callback) {
 | 
						|
  // Pre-flight with HEAD if we don't have a nonce
 | 
						|
  if (this.nonces.length == 0) {
 | 
						|
    this.getNonce(url, function() {
 | 
						|
      this.post(url, body, callback);
 | 
						|
    }.bind(this))
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  console.log("Using nonce: " + this.nonces[0]);
 | 
						|
  var payload = JSON.stringify(body, null, 2);
 | 
						|
  var jws = cryptoUtil.generateSignature(this.privateKey,
 | 
						|
                                         new Buffer(payload),
 | 
						|
                                         this.nonces.shift());
 | 
						|
  var signed = JSON.stringify(jws, null, 2);
 | 
						|
 | 
						|
  console.log('Posting to', url, ':');
 | 
						|
  console.log(signed.green);
 | 
						|
  console.log('Payload:')
 | 
						|
  console.log(payload.blue);
 | 
						|
  var req = request.post({
 | 
						|
    url: url,
 | 
						|
    body: signed,
 | 
						|
    // Return body as buffer, needed for certificate response
 | 
						|
    encoding: null,
 | 
						|
  }, function(error, response, body) {
 | 
						|
    if (error) {
 | 
						|
      console.error(error);
 | 
						|
      process.exit(1);
 | 
						|
    }
 | 
						|
    if (response) {
 | 
						|
      console.log(("HTTP/1.1 " + response.statusCode).yellow)
 | 
						|
    }
 | 
						|
    Object.keys(response.headers).forEach(function(key) {
 | 
						|
      var value = response.headers[key];
 | 
						|
      var upcased = key.charAt(0).toUpperCase() + key.slice(1);
 | 
						|
      console.log((upcased + ": " + value).yellow)
 | 
						|
    });
 | 
						|
    console.log()
 | 
						|
 | 
						|
    // Don't print non-ASCII characters (like DER-encoded cert) to the terminal
 | 
						|
    if (body && !body.toString().match(/[^\x00-\x7F]/)) {
 | 
						|
      try {
 | 
						|
        var parsed = JSON.parse(body);
 | 
						|
        console.log(JSON.stringify(parsed, null, 2).cyan);
 | 
						|
      } catch (e) {
 | 
						|
        console.log(body.toString().cyan);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // Remember the nonce provided by the server
 | 
						|
    if ("replay-nonce" in response.headers) {
 | 
						|
      console.log("Storing nonce: " + response.headers["replay-nonce"]);
 | 
						|
      this.nonces.push(response.headers["replay-nonce"]);
 | 
						|
    }
 | 
						|
 | 
						|
    callback(error, response, body)
 | 
						|
  }.bind(this));
 | 
						|
  req.on('response', function(response) {
 | 
						|
  })
 | 
						|
  return req;
 | 
						|
}
 | 
						|
 | 
						|
module.exports = Acme;
 |