Python输入验证和边缘大小写处理

2024-09-30 01:30:19 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有比我在这个函数中使用的更好的输入验证模式?在

https://github.com/nathancahill/clearbit-intercom/blob/133e4df0cfd1a146cedb3c749fc1b4fac85a6e1b/server.py#L71

这是一个没有经过任何验证的函数。它的可读性更高,短小精悍(9点对53点)。在

def webhook(clearbitkey, appid, intercomkey):
    event = request.get_json()

    id = event['data']['item']['id']
    email = event['data']['item']['email']

    person = requests.get(CLEARBIT_USER_ENDPOINT.format(email=email), auth=(clearbitkey, '')).json()
    domain = person['employment']['domain']

    company = requests.get(CLEARBIT_COMPANY_ENDPOINT.format(domain=domain), auth=(clearbitkey, '')).json()
    note = create_note(person, company)

    res = requests.post(INTERCOM_ENDPOINT,
                        json=dict(user=dict(id=id), body=note),
                        headers=dict(accept='application/json'),
                        auth=(appid, intercomkey))

    return jsonify(note=res.json())

但是,它不处理以下任何错误:

  • dict键错误(特别是嵌套dict)
  • HTTP错误
  • 无效的JSON
  • 意外响应

有没有更好的模式可以遵循?我曾考虑过使用像voluptous这样的数据验证库,但似乎我仍然存在同样的冗长问题。在


Tags: 函数autheventidjsongetemaildomain
1条回答
网友
1楼 · 发布于 2024-09-30 01:30:19

Giton Hub的原始代码看起来不错。它有点过于复杂,但也能处理所有的错误情况。你可以通过抽象的东西来提高可读性。在

为了演示,我可以写这样的代码:

class ValidationError(Exception):
    "Raises when data validation fails"
    pass


class CallExternalApiError(Exception):
    "Raises when calling external api fails"
    pass


def get_user_from_event(event):
    """Get user profile from event

    :param dict event: request.get_json() result
    :returns: A dict of user profile
    """
    try:
        event_type = event['data']['item']['type']
    except KeyError:
        raise ValidationError('Unexpected JSON format.')
    if event_type != 'user':
        return ValidationError('Event type is not supported.')

    try:
        id = event['data']['item']['id']
        email = event['data']['item']['email']
    except KeyError:
        return ValidationError('User object missing fields.')
    return {'id': id, 'email': email}


def call_json_api(request_function, api_name, *args, **kwargs):
    """An simple wrapper for sending request

    :param request_function: function used for sending request
    :param str api_name: name for this api call
    """
    try:
        res = request_function(*args, **kwargs)
    except:
        raise CallExternalApiError('API call failed to %s.' % api_name)

    try:
        return res.json()
    except:
        raise CallExternalApiError('Invalid response from %s.' % api_name)


@app.route('/<clearbitkey>+<appid>:<intercomkey>', methods=['POST'])
def webhook(clearbitkey, appid, intercomkey):
    """
    Webhook endpoint for Intercom.io events. Uses this format for Clearbit and
    Intercom.io keys:
    /<clearbitkey>+<appid>:<intercomkey>
    :clearbitkey: Clearbit API key.
    :appid: Intercom.io app id.
    :intercomkey: Intercom.io API key.
    Supports User events, specifically designed for the User Created event.
    Adds a note to the user with their employment and company metrics.
    """
    event = request.get_json()
    try:
        return handle_event(event, clearbitkey, appid, intercomkey)
    except (ValidationError, CallExternalApiError) as e:
        # TODO: include **res_objs in response
        return jsonify(error=str(e))


def handle_event(event):
    """Handle the incoming event
    """
    user = get_user_from_event(event)
    res_objs = dict(event=event)

    person = call_json_api(
        requests.get,
        'Clearbit',
        CLEARBIT_USER_ENDPOINT.format(email=user['email']),
        auth=(clearbitkey, '')
    )

    res_objs['person'] = person
    if 'error' in person:
        raise CallExternalApiError('Error response from Clearbit.')

    domain = person['employment']['domain']
    company = None

    if domain:
        try:
            company = call_json_api(
                requests.get,
                'Clearbit',
                CLEARBIT_COMPANY_ENDPOINT.format(domain=domain),
                auth=(clearbitkey, ''))
            )
            if 'error' in company:
                company = None
        except:
            company = None

    res_objs['company'] = company

    try:
        note = create_note(person, company)
    except:
        return jsonify(error='Failed to generate note for user.', **res_objs)

    result = call_json_api(
        requests.post,
        'Intercom',
        (INTERCOM_ENDPOINT, json=dict(user=dict(id=id), body=note),
        headers=dict(accept='application/json'),
        auth=(appid, intercomkey)
    )
    return jsonify(note=result, **res_objs)

我希望有帮助。在

相关问题 更多 >

    热门问题