Access-Control-Allow-Origin is not showing up in r

2019-02-11 01:59发布

问题:

My Codeigniter file says

$CI->output->set_header("Access-Control-Allow-Origin: *");
$CI->output->set_header("Access-Control-Expose-Headers: Access-Control-Allow-Origin");
$CI->output->set_status_header(200);
$CI->output->set_content_type('application/json');
echo json_encode(array("city" => "dhaka"));

but the http response that i get are:

Request URL:http://localhost/index.php/location/city
Request Method:POST
Status Code:200 OK

Connection:Keep-Alive
Content-Length:16
Content-Type:text/html
Date:Sun, 22 Jul 2012 10:27:32 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.2.21 (Unix) mod_ssl/2.2.21 OpenSSL/0.9.8r DAV/2 PHP/5.3.6
X-Powered-By:PHP/5.3.6

The header Access-Control-Allow-Origin is missing in the response even after including Access-Control-Expose-Headers: Access-Control-Allow-Origin. My source of information about this header is from Mozilla Developer Website

回答1:

It turns out, it worked for me only when i set the headers via the PHP syntax header() instead of the codeigniter syntax $CI->output->set_header(). That's sad.

Thanks to the first comment by @Yan at the Question of this topic



回答2:

If you look closely you can also notice the content-type being different: it's text/html, whereas you are requesting application/json. This happens because while you are preparing the headers correctly, you never actually output them. As far as I know you can do this in at least 2 ways:

  1. Use the output library's set_output function to output everything at once.

    $json = json_encode(array("city" => "dhaka"));
    
    $this->output->set_header("Access-Control-Allow-Origin: *");
    $this->output->set_header("Access-Control-Expose-Headers: Access-Control-Allow-Origin");
    $this->output->set_status_header(200);
    $this->output->set_content_type('application/json');
    
    $this->output->set_output($json);
    
  2. Call the output-library's _display() function, to first output the correct headers and then append your json object with echo.

    $this->output->set_header("Access-Control-Allow-Origin: *");
    $this->output->set_header("Access-Control-Expose-Headers: Access-Control-Allow-Origin");
    $this->output->set_status_header(200);
    $this->output->set_content_type('application/json');
    $this->output->_display();
    
    echo json_encode(array("city" => "dhaka"));
    

    This function sends the finalized output data to the browser along with any server headers and profile data. (From CI/system/core/Output.php line 316)



回答3:

after some digging around, i found that $CI->output->set_header() does work - when there isn't an error or exception.

When there is an error or exception that CI can catch, the output & view classes are bypassed completely and the appropriate error pages are rendered with include(VIEWPATH.'errors/'.$template.'.php') and headers sent with set_status_header($status_code) (located at <CI System Dir>/core/Common.php)

see <CI System Dir>/core/Exceptions.php

here's a sample:

    /**
     * General Error Page
     *
     * Takes an error message as input (either as a string or an array)
     * and displays it using the specified template.
     *
     * @param   string      $heading    Page heading
     * @param   string|string[] $message    Error message
     * @param   string      $template   Template name
     * @param   int     $status_code    (default: 500)
     *
     * @return  string  Error page output
     */
    public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
    {
        set_status_header($status_code);

        $message = '<p>'.implode('</p><p>', is_array($message) ? $message : array($message)).'</p>';

        if (ob_get_level() > $this->ob_level + 1)
        {
            ob_end_flush();
        }
        ob_start();
        include(VIEWPATH.'errors/'.$template.'.php');
        $buffer = ob_get_contents();
        ob_end_clean();
        return $buffer;
    }

it's annoying in that it makes DRY less straight forward. to work around it, i suggest you create a helper function, for example (untested):

function my_generate_headers($headers=array(),$useOutputClass=true)
{
    if(is_array($headers) && count($headers)<1) return false;

    foreach($headers AS $eHeader)
    {
        ($useOutputClass) ? 
                    get_instance()->output->set_header('X-Powered-By: C-C-C-Cocaine') : 
                    @header('X-Powered-By: Errors',true);
    }

    return true;
}

use that function in your different error pages at <CI Views>/errors/error_*.php as well as in your controllers.



回答4:

What worked for me is:

$this->output
  ->set_header('Access-Control-Allow-Origin: http://localhost:4567')
  ->set_header('Content-type: application/json')
  ->set_status_header(200)
  ->set_output( json_encode($to_encode) )
  ->_display();