用javascript和python base http server

时间:2016-07-13 03:37:28

标签: javascript python ajax cors preflight

我无法使用以下java脚本。

window.onload = function() {
  mycallback(dataParm);
};

function mycallback(data) {
    console.log(data);
    return true;
}

var xhr = $.ajax({
    url: connectionUri,
    dataType: 'json',
    type: 'GET',
    headers: {
        "Authorization":"Basic " + btoa(userName + ":" + password)          },
    success: function (data) {
        console.log("In Success");
        document.getElementById("id01").innerHTML = data;
    },
    error:  function (xhr, ajaxOptions, thrownError) {
        console.log("Connection error: " + xhr.responseText + "\n" + thrownError);  
    }
});

我修改了服务器的以下python脚本

"""Preflight CORS HTTP Server.

This is modified version of SimpleHTTPRequestHandler
This module builds on BaseHTTPServer by implementing the standard GET
and HEAD requests in a fairly straightforward manner.

"""


__version__ = "1.0"

__all__ = ["PreflightCORSHandler"]

import os
import posixpath
import BaseHTTPServer
import urllib
import cgi
import shutil
import mimetypes
from StringIO import StringIO


class PreflightCORSHandler(BaseHTTPServer.BaseHTTPRequestHandler):

    """PreflightCORS HTTP request handler with GET and HEAD commands.

    This serves files from the current directory and any of its
    subdirectories.  It assumes that all files are plain text files
    unless they have the extension ".html" in which case it assumes
    they are HTML files.

    The GET and HEAD requests are identical except that the HEAD
    request omits the actual contents of the file.

    """

    server_version = "PreflightCORSHTTP/" + __version__

    def do_GET(self):
        """Serve a GET request."""
        f = self.send_head()
        if f:
            self.copyfile(f, self.wfile)
            f.close()

    def do_OPTIONS(self):           
        self.send_response(200, "ok")       
        self.send_header("Access-Control-Allow-Origin", "http://localhost:8889")
        self.send_header("Access-Control-Allow-Credentials", "true")
        self.send_header("Access-Control-Allow-Methods", "GET")
        self.send_header("Access-Control-Allow-Headers", "dataType, accept, authorization") 

    def do_HEAD(self):
        """Serve a HEAD request."""
        f = self.send_head()
        if f:
            f.close()

    def send_head(self):
        """Common code for GET and HEAD commands.

        This sends the response code and MIME headers.

        Return value is either a file object (which has to be copied
        to the outputfile by the caller unless the command was HEAD,
        and must be closed by the caller under all circumstances), or
        None, in which case the caller has nothing further to do.

        """
        path = self.translate_path(self.path)
        f = None
        if os.path.isdir(path):
            for index in "index.html", "index.htm":
                index = os.path.join(path, index)
                if os.path.exists(index):
                    path = index
                    break
            else:
                return self.list_directory(path)
        ctype = self.guess_type(path)
        if ctype.startswith('text/'):
            mode = 'r'
        else:
            mode = 'rb'
        try:
            f = open(path, mode)
        except IOError:
            self.send_error(404, "File not found")
            return None
        self.send_response(200)
        self.send_header("Content-type", ctype)
        self.send_header("Access-Control-Allow-Origin", "http://localhost:8889")
        self.send_header("Access-Control-Allow-Credentials", "true")
        self.send_header("Access-Control-Allow-Methods", "GET")
        self.send_header("Access-Control-Allow-Headers", "dataType, accept, authorization") 
        self.end_headers()
        return f

    def list_directory(self, path):
        """Helper to produce a directory listing (absent index.html).

        Return value is either a file object, or None (indicating an
        error).  In either case, the headers are sent, making the
        interface the same as for send_head().

        """
        try:
            list = os.listdir(path)
        except os.error:
            self.send_error(404, "No permission to list directory")
            return None
        list.sort(lambda a, b: cmp(a.lower(), b.lower()))
        f = StringIO()
        f.write("<title>Directory listing for %s</title>\n" % self.path)
        f.write("<h2>Directory listing for %s</h2>\n" % self.path)
        f.write("<hr>\n<ul>\n")
        for name in list:
            fullname = os.path.join(path, name)
            displayname = linkname = name = cgi.escape(name)
            # Append / for directories or @ for symbolic links
            if os.path.isdir(fullname):
                displayname = name + "/"
                linkname = name + "/"
            if os.path.islink(fullname):
                displayname = name + "@"
                # Note: a link to a directory displays with @ and links with /
            f.write('<li><a href="%s">%s</a>\n' % (linkname, displayname))
        f.write("</ul>\n<hr>\n")
        f.seek(0)
        self.send_response(200)
        self.send_header("Content-type", "text/html")
        self.end_headers()
        return f

    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        """
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = os.getcwd()
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)
        return path

    def copyfile(self, source, outputfile):
        """Copy all data between two file objects.

        The SOURCE argument is a file object open for reading
        (or anything with a read() method) and the DESTINATION
        argument is a file object open for writing (or
        anything with a write() method).

        The only reason for overriding this would be to change
        the block size or perhaps to replace newlines by CRLF
        -- note however that this the default server uses this
        to copy binary data as well.

        """
        shutil.copyfileobj(source, outputfile)

    def guess_type(self, path):
        """Guess the type of a file.

        Argument is a PATH (a filename).

        Return value is a string of the form type/subtype,
        usable for a MIME Content-type header.

        The default implementation looks the file's extension
        up in the table self.extensions_map, using text/plain
        as a default; however it would be permissible (if
        slow) to look inside the data to make a better guess.

        """

        base, ext = posixpath.splitext(path)
        if self.extensions_map.has_key(ext):
            return self.extensions_map[ext]
        ext = ext.lower()
        if self.extensions_map.has_key(ext):
            return self.extensions_map[ext]
        else:
            return self.extensions_map['']

    extensions_map = mimetypes.types_map.copy()
    extensions_map.update({
        '': 'application/octet-stream', # Default
        '.py': 'text/plain',
        '.c': 'text/plain',
        '.h': 'text/plain',
        })


def test(HandlerClass = PreflightCORSHandler,
         ServerClass = BaseHTTPServer.HTTPServer):
    BaseHTTPServer.test(HandlerClass, ServerClass)


if __name__ == '__main__':
    test()

我从Chrome调试器收到以下错误。 (我基本上只想让它与Chrome合作)

XMLHttpRequest cannot load https://services.yesenergy.com/PS/rest/constraint/HOURLY/RTPD/CAISO.json?startdate=2016-05-01. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8889' is therefore not allowed access. The response had HTTP status code 401.

以下是我从Fiddler Inspector获得的内容

初始请求标题

GET http://localhost:8889/test.html HTTP/1.1
Host: localhost:8889
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

初始回复标题

HTTP/1.0 200 OK
Server: PreflightCORSHTTP/1.0 Python/2.7.6
Date: Wed, 13 Jul 2016 01:38:15 GMT
Content-type: text/html
Access-Control-Allow-Origin: http://localhost:8889
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET
Access-Control-Allow-Headers: dataType, accept, authorization

预检请求标题

OPTIONS https://services.yesenergy.com/PS/rest/constraint/HOURLY/RTPD/CAISO.json?startdate=2016-05-01 HTTP/1.1
Host: services.yesenergy.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: GET
Origin: http://localhost:8889
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Access-Control-Request-Headers: dataType, accept, authorization
Accept: */*
Referer: http://localhost:8889/test.html
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6

预检响应(不是100%确定预检是否响应,但它是对上述请求的响应)

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1059
Date: Wed, 13 Jul 2016 01:38:15 GMT
Server: Apache

<html><head><title>Apache Tomcat/7.0.x - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 401 - Full authentication is required to access this resource</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Full authentication is required to access this resource</u></p><p><b>description</b> <u>This request requires HTTP authentication.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.x</h3></body></html>

使用以下网址和正确的用户名和密码直接拨打网站获取完全相同的信息完全正常。

https://username:password@services.yesenergy.com/PS/rest/constraint/HOURLY/RTPD/CAISO.json?startdate=2016-05-01

感觉就像是与身份验证相关的内容,即使Google调试器说预检电话在获取“访问控制 - 允许 - 来源”方面存在问题。头。我可能是错的,可能错过了一些东西,并且无法使Origin头工作。

我确实尝试过向Access-Control-Allow-Methods添加额外的方法,例如OPTIONS和POST,但它没有任何区别。

任何建议或帮助都会很棒。

0 个答案:

没有答案