I'm writing a routing system that may or may not be part of a public API later for a personal project. A main part of the routing system is a response object for the user to send headers, status code, and the body of the response that is sent from the server.
I've created a response class that I think covers everything the user would want to do with the response (it could use a few more "convenience" functions however). I wanted to post it here to make sure my code is clean, and that I didn't miss anything that the end user might want to do.
An instance of the request class is provided to the user when a request is made to a specified URL (see my last code review)
I present my response class:
    class Response {
    private $headers = array();
    private $code = 200;
    private $body = '';
    private $sent = false;
    private $log;
    public function __construct() {
        $this->log = Logger::getLogger(get_class($this));
    }
    public function headers ($headers) { // Add some headers to the headers array
        $this->headers = array_merge($this->headers, $headers);
        return $this;
    }
    public function header ($key, $value) { // set a single header in the headers array
        $this->headers[$key] = $value;
        return $this;
    }
    public function code ($code) { // Set the status code
        $this->code = $code;
        return $this;
    }
    public function status ($code) { // Alternate method for setting the status code
        return $this->code($code);;
    }
    public function json($str) { // respond with json, set the body text and set the content-type header
        $this->header('Content-Type', 'application/json');
        if(is_array($str)) { // handle either raw JSON text, or php arrays
            $this->body = json_encode($str);
        } else {
            $this->body = $str;
        }
        return $this;
    }
    public function html ($str){ // respond with HTML
        $this->header('Content-Type', 'text/html');
        $this->body = $str;
        return $this;
    }
    public function form ($str) { // Respond with form data
        $this->header('Content-Type', 'application/x-www-form-urlencoded');
        // TODO: Allow the user to user an array
        $this->body = $str;
        return $this;
    }
    public function render ($file){ // Render an HTML file from the templates folder
        //TODO: Restrict to templates folder open
        //TODO: Add server-side rendering code
        $this->body = file_get_contents($file);
        return $this;
    }
    public function sent() { // Check if the request has been sent
        return $this->sent;
    }
    public function send () { // send the request
        if($this->sent()){
            $log->error('Attempted to call send on a sent response!');
            exit('Attempted to call send on a sent response!');
        }
        // Log the request for debugging
        $this->log->info($this->headers);
        $this->log->info('HTTP Responce Code: ' . $this->code);
        $this->log->info($this->body);
        // Set the headers
        foreach($this->headers as $key => $value) {
            header($key .': ' . $value);
        }
        // Set the status code
        http_response_code($this->code);
        // Send out the body
        echo $this->body;
        // Set the sent variable
        $this->sent = true;
    }
}
EDIT:
The idea with the short and clear function names that all return $this is to be able to have clear and simple chainable responses. (e.g $res->code(200)->json(... Json...);) 

