嗨我需要一些基本身份验证的帮助,而ajax get / post请求到python baseHTTPserver.

我能够在python脚本中更改一些代码行来发送CORS头.当我禁用http base authentification时,它在现代浏览器中工作正常.

如果启用了身份验证,我会收到501(不支持的方法(‘OPTIONS’))错误(i chrome).

我花了好几个小时寻找一个解决方案现在我认为我是一个好方法.正如我在下面的主题中读到的,HTTPRequestHandler可能会导致问题,但我的pyton技能不足以解决问题.

如果发现一些关于这个话题here和here的帖子,但我无法使用我的脚本运行它.有人可以帮助我让它运行吗?

任何帮助或想法都将受到高度赞赏.

#   copyright 2012-2013 Eric Ptak - trouch.com
    #
    #   Licensed under the Apache License,Version 2.0 (the "License");
    #   you may not use this file except in compliance with the License.
    #   You may obtain a copy of the License at
    #
    #       http://www.apache.org/licenses/LICENSE-2.0
    #
    #   Unless required by applicable law or agreed to in writing,software
    #   distributed under the License is distributed on an "AS IS" BASIS,#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied.
    #   See the License for the specific language governing permissions and
    #   limitations under the License.

    import os
    import threading
    import re
    import codecs
    import mimetypes as mime
    import logging

    from webiopi.utils import *

    if PYTHON_MAJOR >= 3:
        import http.server as BaseHTTPServer
    else:
        import BaseHTTPServer

    try :
        import _webiopi.GPIO as GPIO
    except:
        pass

    WEBIOPI_DOCROOT = "/usr/share/webiopi/htdocs"

    class HTTPServer(BaseHTTPServer.HTTPServer,threading.Thread):
        def __init__(self,host,port,handler,context,docroot,index,auth=None):
            BaseHTTPServer.HTTPServer.__init__(self,("",port),HTTPHandler)
            threading.Thread.__init__(self,name="HTTPThread")
            self.host = host
            self.port = port

            if context:
                self.context = context
                if not self.context.startswith("/"):
                    self.context = "/" + self.context
                if not self.context.endswith("/"):
                    self.context += "/"
            else:
                self.context = "/"

            self.docroot = docroot

            if index:
                self.index = index
            else:
                self.index = "index.html"

            self.handler = handler
            self.auth = auth

            self.running = True
            self.start()

        def get_request(self):
            sock,addr = self.socket.accept()
            sock.settimeout(10.0)
            return (sock,addr)

        def run(self):
            info("HTTP Server binded on http://%s:%s%s" % (self.host,self.port,self.context))
            try:
                self.serve_forever()
            except Exception as e:
                if self.running == True:
                    exception(e)
            info("HTTP Server stopped")

        def stop(self):
            self.running = False
            self.server_close()

    class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
        logger = logging.getLogger("HTTP")

        def log_message(self,fmt,*args):
            self.logger.debug(fmt % args)

        def log_error(self,*args):
            pass

        def version_string(self):
            return VERSION_STRING

        def checkAuthentication(self):
            if self.server.auth == None or len(self.server.auth) == 0:
                return True

            authHeader = self.headers.get('Authorization')
            if authHeader == None:
                return False

            if not authHeader.startswith("Basic "):
                return False

            auth = authHeader.replace("Basic ","")
            if PYTHON_MAJOR >= 3:
                auth_hash = encrypt(auth.encode())
            else:
                auth_hash = encrypt(auth)

            if auth_hash == self.server.auth:
                return True
            return False

        def requestAuthentication(self):
            self.send_response(401)
            self.send_header("WWW-Authenticate",'Basic realm="webiopi"')
            self.end_headers();

        def sendResponse(self,code,body=None,type="text/plain"):
            if code >= 400:
                if body != None:
                    self.send_error(code,body)
                else:
                    self.send_error(code)
            else:
                self.send_response(code)
                self.send_header("Cache-Control","no-cache")
                self.send_header("Access-Control-Allow-Origin","*")
                self.send_header("Access-Control-Allow-Methods","POST,GET")
                self.send_header("Access-Control-Allow-Headers"," X-Custom-Header")
                if body != None:
                    self.send_header("Content-Type",type);
                    self.end_headers();
                    self.wfile.write(body.encode())

        def findFile(self,filepath):
            if os.path.exists(filepath):
                if os.path.isdir(filepath):
                    filepath += "/" + self.server.index
                    if os.path.exists(filepath):
                        return filepath
                else:
                    return filepath
            return None


        def serveFile(self,relativePath):
            if self.server.docroot != None:
                path = self.findFile(self.server.docroot + "/" + relativePath)
                if path == None:
                    path = self.findFile("./" + relativePath)

            else:
                path = self.findFile("./" + relativePath)                
                if path == None:
                    path = self.findFile(WEBIOPI_DOCROOT + "/" + relativePath)

            if path == None and (relativePath.startswith("webiopi.") or relativePath.startswith("jquery")):
                path = self.findFile(WEBIOPI_DOCROOT + "/" + relativePath)

            if path == None:
                return self.sendResponse(404,"Not Found")

            realPath = os.path.realpath(path)

            if realPath.endswith(".py"):
                return self.sendResponse(403,"Not Authorized")

            if not (realPath.startswith(os.getcwd()) 
                    or (self.server.docroot and realPath.startswith(self.server.docroot))
                    or realPath.startswith(WEBIOPI_DOCROOT)):
                return self.sendResponse(403,"Not Authorized")

            (type,encoding) = mime.guess_type(path)
            f = codecs.open(path,encoding=encoding)
            data = f.read()
            f.close()
            self.send_response(200)
            self.send_header("Content-Type",type);
            self.send_header("Content-Length",os.path.getsize(realPath))
            self.end_headers()
            self.wfile.write(data)

        def processRequest(self):
            self.request.settimeout(None)
            if not self.checkAuthentication():
                return self.requestAuthentication()

            request = self.path.replace(self.server.context,"/").split('?')
            relativePath = request[0]
            if relativePath[0] == "/":
                relativePath = relativePath[1:]

            if relativePath == "webiopi" or relativePath == "webiopi/":
                self.send_response(301)
                self.send_header("Location","/")
                self.end_headers()
                return

            params = {}
            if len(request) > 1:
                for s in request[1].split('&'):
                    if s.find('=') > 0:
                        (name,value) = s.split('=')
                        params[name] = value
                    else:
                        params[s] = None

            compact = False
            if 'compact' in params:
                compact = str2bool(params['compact'])

            try:
                result = (None,None,None)
                if self.command == "GET":
                    result = self.server.handler.do_GET(relativePath,compact)
                elif self.command == "POST":
                    length = 0
                    length_header = 'content-length'
                    if length_header in self.headers:
                        length = int(self.headers[length_header])
                    result = self.server.handler.do_POST(relativePath,self.rfile.read(length),compact)
                else:
                    result = (405,None)

                (code,body,type) = result

                if code > 0:
                    self.sendResponse(code,type)
                else:
                    if self.command == "GET":
                        self.serveFile(relativePath)
                    else:
                        self.sendResponse(404)

            except (GPIO.InvalidDirectionException,GPIO.InvalidChannelException,GPIO.SetupException) as e:
                self.sendResponse(403,"%s" % e)
            except ValueError as e:
                self.sendResponse(403,"%s" % e)
            except Exception as e:
                self.sendResponse(500)
                raise e

        def do_GET(self):
            self.processRequest()

        def do_POST(self):
            self.processRequest()

解决方法

客户端应发出两个请求,首先是一个OPTIONS,然后是GET请求.所提出的解决方案并非最佳,因为我们正在回答带有内容的OPTIONS请求.
def do_OPTIONS(self):
            self.sendResponse(200)
            self.processRequest() # not good!

我们应该正确回答OPTIONS请求.如果我们这样做,客户端将在收到正确答案后发出GET请求.

我得到了由CORS引起的501 Unsupported方法(‘OPTIONS’))并请求“Content-Type:application / json; charset = utf-8”.

为了解决这个错误,我在do_OPTIONS中启用了CORS,并使客户端能够请求特定的内容类型.

我的解决方案

def do_OPTIONS(self):
    self.send_response(200,"ok")
    self.send_header('Access-Control-Allow-Origin','*')
    self.send_header('Access-Control-Allow-Methods','GET,OPTIONS')
    self.send_header("Access-Control-Allow-Headers","X-Requested-With")
    self.send_header("Access-Control-Allow-Headers","Content-Type")
    self.end_headers()

 def do_GET(self):
    self.processRequest()

jquery – 在chrome中使用python baseHTTPserver 501(不支持的方法(‘OPTIONS’))的CORS的更多相关文章

  1. AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas的示例代码

    这篇文章主要介绍了AmazeUI 手机版页面的顶部导航条Header与侧边导航栏offCanvas,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. xcode – Cordova plugin.xml添加“Header Search Paths”条目

    我希望将Cordova插件添加到Xcode项目后,在“HeaderSearchPaths”下添加一个新条目.如何在Cordovaplugin.xml文件中进行配置?

  3. ios – iPhone 6 Plus横向模式中的奇怪错误,带有标签和固定元素

    我有一些疯狂的问题iPhone6Safari(主要是iOS9,虽然iOS8也有一些小故障),标签模式打开.所有固定元素都以纵向和横向正确定位,但在横向模式下不可见和/或移动,并打开一个或多个标签.即使它们不可见,它们仍然可以点击并与其他内容重叠.旋转设备在一定程度上解决了问题,以及在标签之间切换.将元素位置从固定设置为静态和背面也有帮助.HTML:CSS:应用程序非常大,但我已经成功地在codep

  4. ios – 使用CocoaPods post install hook将自定义路径添加到HEADER_SEARCH_PATHS

    解决方法在Podfile中定义一个方法:然后在post_install中调用该方法:

  5. XCode 3.2 Ruby和Python模板

    在xcode3.2下,我的ObjectiveCPython/Ruby项目仍然可以打开更新和编译,但是你无法创建新项目.鉴于xcode3.2中缺少ruby和python的所有痕迹(即创建项目并添加新的ruby/python文件),是否有一种简单的方法可以再次安装模板?我发现了一些关于将它们复制到某个文件夹的信息,但我似乎无法让它工作,我怀疑文件夹的位置已经改变为3.2.解决方法3.2中的应用程序模板

  6. ios – 如何使用XIB自定义tableView Section Header?

    我正在尝试为UITableView创建自定义的节标题.我找到了一些参考资料,说明如何在代码中完成这项工作.我试图确定是否可以在InterfaceBuilder中创建UIView并使用它来自定义标题,类似于如何为UITableViewCell执行此操作?

  7. Swift基本使用-函数和闭包(三)

    声明函数和其他脚本语言有相似的地方,比较明显的地方是声明函数的关键字swift也出现了Python中的组元,可以通过一个组元返回多个值。传递可变参数,函数以数组的形式获取参数swift中函数可以嵌套,被嵌套的函数可以访问外部函数的变量。可以通过函数的潜逃来重构过长或者太复杂的函数。

  8. swift - The Proxy Pattern

    我在实际工作中vc也仿照过Foundation的delegate:button:内涵业务逻辑,底层实现;每个button是一个类,业务逻辑需要未知的参数和处理之后未知的结果反馈UI:点击button之后界面的改变,UI实现未知的参数和未知的结果反馈,也就是实现这个代理这样以来UI的定制,很灵活很容易,代码思路依然清晰如初。哪个是主体哪个是代理并不重要关键是看定义所说whichisusedwhenanobjectisrequiredtoactasaninterfacetoanotherobjectorres

  9. 10 个Python中Pip的使用技巧分享

    众所周知,pip 可以安装、更新、卸载 Python 的第三方库,非常方便。本文小编为大家总结了Python中Pip的使用技巧,需要的可以参考一下

  10. Swift 引入 Object-c 代码

    如果要在Swift引入OC的代码:1.创建一个header文件工程名:Bridging-Header.h2、设置path在target-BuildSettings-SwiftCompiler-CodeGeneration中的Object-cBridgingHeader填入此文件的路径,这个路径是基于项目工程文件夹的,写的时候注意,如果出错,看日志查路径即可。

随机推荐

  1. jquery-plugins – 是否可以使用猫头鹰旋转木马实现循环/无限轮播?

    我正在使用猫头鹰旋转木马,它的工作完美,除了它不支持循环/无限滚动.我没有搜索google和stackoverflow的想法,没有运气.有没有人在猫头鹰旋转木马上实现圆形/无限滚动?

  2. jQuery动态输入字段焦点

    我想使用以下jQuery向我的页面动态添加一个输入字段:在这样做之后,我希望输入字段具有闪烁的文本光标的焦点,所以我想在创建后立即输入.有人可以告诉我我该怎么办?

  3. jquery – 为什么$(window).height()这样错了?

    我试图获取当前浏览器的视口高度,使用但我得到的价值观太低了.当视口高度高达850px时,我从height()获取大约350或400像素的值.这是怎么回事?

  4. jquery – 如果在此div之外和其他draggables内部(使用无效和有效的还原选项),则可拖动恢复

    例如这样但是由于明显的原因,这不行.我可以说这个吗?

  5. 创建一个jQueryUI 1.8按钮菜单

    现在jQueryUI1.8已经出来了,我正在浏览更新,并且遇到了新的Buttonwidget,特别是SplitButtonwithadropdown的演示之一.这个演示似乎表明Buttonwidget可以在这里创建一个下拉菜单.作为讨论的问题,我想知道使用这个新的Button小部件来创建一个下拉菜单有什么方法.干杯.解决方法您必须在按钮下方列出一个列表,方式类似于此处为自动完成提供的演示:http

  6. 灰色divs使用JQuery

    我试图使用这个代码:为了淡出一大堆名为MySelectorDiv的div,唯一的是,它只会淡出第一个而不是所有的div,为什么呢?

  7. 使用jQuery动态插入到列表中

    我有两个订单列表在彼此旁边.当我从一个列表中选出一个节点时,我想按照字母顺序插入到另一个列表中.抓住的是我想要把一个元素放在另一个列表中,而不刷新整个列表.奇怪的是,当我插入到右边的列表中,它工作正常,但是当我插入到左边的列表中时,顺序永远不会出来.我也尝试将所有内容读入数组,并将其排序在一起,以防止children()方法没有按照显示顺序返回任何东西,但是我仍然得到相同的结果.这是我的jQuer

  8. 没有回应MediaWiki API使用jQuery

    我试图从维基百科获取一些内容作为JSON:但我没有回应.如果我粘贴到浏览器的地址栏,就像我得到预期的内容.怎么了?解决方法您需要通过添加&callback=?来触发具有$.getJSON()的JSONP行为?在querystring上,像这样:Youcantestithere.没有使用JSONP,你正在击中same-originpolicy,阻止XmlHttpRequest获取任何数据.

  9. jQuery Ajax请求每30秒

    我有这段代码,但是有些人在我的网站上的值可能会改变.我需要每30秒钟更新一次#financediv.这可以做吗解决方法您可以将代码放在单独的函数中,如下所示:然后每30秒建立一个定时器调用该函数:祝你好运!总结以上是DEVMAX为你收集整理的jQueryAjax请求每30秒全部内容。如果觉得DEVMAX网站内容还不错,欢迎将DEVMAX网站推荐给好友。

  10. jquery – keypress事件在IE和Chrome中不工作,但在FF工作

    任何想法为什么会这样发生?我通常认为Chrome会更加宽容代码?这是我的按键键.我错过了什么吗?右图();和leftimage();是应该工作的功能,因为我在其他地方使用这些功能谢谢您的帮助!

返回
顶部