2011-11-19 2 views
3

대부분의 cherrypy 개발자는 서버 측 폼 검증을 위해 무엇을합니까? 나는 구글을 해봤지만 "그것을하는 한 가지 방법"으로 뛰어 내리지 못한 것은 아무것도 없다.체리 형태 확인

답변

5

당신은 도구를 작성하고 장식

로 사용 또는 내 검증 장식을 사용할 수 있습니다 :

import re 
from simplejson import JSONDecoder 
from simplejson.decoder import JSONDecodeError 
#from cherrypy._cperror import HTTPError 
from decimal import Decimal 

class ValidationException(Exception): 
    pass 

class ArgumentException(ValidationException): 
    pass 

class MandatoryException(ValidationException): 
    pass 

class DenialException(ValidationException): 
    pass 

class ParameterTypeException(ValidationException): 
    pass 

class ParameterValueException(ValidationException): 
    pass 

def validate_parameters(args,kwargs,required_args=None 
            ,deny_args=None 
            ,requires=None 
            ,deny=None 
            ,deny_except=None 
            ,types=None 
            ,values=None 
            ,filter=None 
            ,json_decode=None 
            ,defaults=None): 
    """Validates input parameters of a callable 

    @param required_arguments: list of types, Required argument's types & counts in order 
    @param deny_args    string ,regex pattern, if any argument matches with the pattern, exception raises 
    @param requires:    list of fields to check for mandatory 
    @param deny:     string ,regex pattern, if any parameter matches with the pattern, exception raises 
    @param deny_except:   string ,regex pattern for excluding fields from deny 
    @param types:    dict of key:name and value:type to check for types, if mismatch it will be raises exception 
    @param values:    dict of key:name and value:regex pattern to check the values, & fire exception if mismatch 
    @param filter:    string ,regex pattern of parameters to filter 
    @param json_decode:   list of string: field to be decoded as json data  
    @param defaults:    dict of key:name and value:default_value 

    @raise MandatoryException:   if any param in requires does not provided 
    @raise ArgumentException:   if arguments are invalid , short or mismatch type. 
    @raise DenialException:    if found param in deny list 
    @raise ParameterTypeException:  if parameter types invalid 
    @raise ParameterValueException:  if values are not in correct format 
    """ 


    #check deny arguments 
    if deny_args: 
     for arg in args: 
      if re.match(deny_args, arg): 
       raise DenialException('the argument %s was not allowed' % arg) 

    #decoding json parameters 
    if json_decode: 
     decoder = JSONDecoder(parse_float=Decimal) 
     def decode(d): 
      try: 
       return decoder.decode(d) 
      except (JSONDecodeError,TypeError): 
       return d 

     if isinstance(json_decode,list): 
      decoded_list =[(key,decode(kwargs[key])) for key in kwargs if key in json_decode] 
     else: 
      decoded_list =[(key,decode(kwargs[key])) for key in kwargs] 
     kwargs.update(decoded_list) 



    #check required arguments 
    if required_args: 
     try: 
      new_args = list(args) 
      for at in required_args: 
       index = required_args.index(at) 
       if not isinstance(new_args[index],at): 
        try: 
         #try to cast 
         new_args[index] = at(new_args[index]) 
        except: 
         raise ParameterTypeException('argument at index:%s must be %s' % (required_args.index(at),at)) 
      args = tuple(new_args) 
     except IndexError: 
      raise ArgumentException('argument\'s length is too short') 

    #check required parameters 
    if requires: 
     for name in requires: 
      if name not in kwargs: 
       raise MandatoryException('the parameter:"%s" is mandatory' % name) 


    filtered_params = {} 
    for param in kwargs: 

     #checking requires 
     if requires and param in requires and not kwargs[param]: 
      raise MandatoryException('the parameter:"%s" is mandatory' % param) 

     #checking for denial 
     if deny and re.match(deny,param) and (not deny_except or not re.match(deny_except, param)): 
      raise DenialException('Parameter: %s was denied' % param) 

     #value checking 
     if values and param in values and not re.match(values[param], kwargs[param]): 
      raise ParameterValueException('Parameter:%s does not meet value pattern: given value:%s' % (param,kwargs[param])) 

     #checking for types 
     if types and param in types: 
      if kwargs[param] and not isinstance(kwargs[param],types[param]): 
       try: 
        #try to cast the type too needed type 
        kwargs[param] = types[param](kwargs[param]) 
       except: 
        raise ParameterTypeException('Parameter:%s must be type:%s, given type:%s' % (param,types[param],type(kwargs[param]))) 


     #filtering parameters 
     if not filter or not re.match(filter,param): 
      filtered_params[param] = kwargs[param] 

    #add defaults if not supplied 
    if defaults: 
     for param in defaults: 
      if param not in filtered_params: 
       filtered_params[param] = defaults[param] 

    return args,filtered_params 


def validate(**val_cfg): 
    def validecorator(func): 
     def wrapper(*args,**kwargs): 
       if len(func.func_code.co_varnames) and func.func_code.co_varnames[0] == 'self': 
        new_args,filtered_params = validate_parameters(args[1:], kwargs,**val_cfg) 
        return func(*(args[0],)+new_args,**filtered_params) 
       else: 
        new_args,filtered_params = validate_parameters(args, kwargs,**val_cfg) 
        return func(*new_args,**filtered_params) 
      #calling the callable! 

     return wrapper 
    return validecorator 

validate.__doc__ = validate_parameters.__doc__ 

예 :

@validate(types={'name':str,age:int},values={'name':'[a-zA-Z]{5,50}',age:'\d{1,2}'}) 
def my_controller(name=None,age=None): 
    # process data 
    return render(\\some template\\) 

가 도움이 될 수 있습니다!

EDIT 1

this 패키지

+0

큰 코드를 살펴 보자! 나는 cherrypy가 앱이 프레임 워크가 아닌 실제 파이썬이라고 생각하게 만드는 것을 좋아합니다. – MKaras

+0

이 코드를 cherrypy 표준 도구로 변환 할 수 있습니다. 그런 다음 on_start_response에서 유효성 검사를 처리하고 적절한 상황에서 HTTPError를 발생시킵니다. – pylover

+0

https://pypi.python.org/pypi/pyvalidate – pylover