python类HTTP_400的实例源码

resources.py 文件源码 项目:gyr 作者: non-Jedi 项目源码 文件源码 阅读 18 收藏 0 点赞 0 评论 0
def on_put(self, request, response, txn_id=None):
        """Responds to PUT request containing events."""
        response.body = "{}"

        # Check whether repeat txn_id
        if not self._is_new(txn_id):
            response.status = falcon.HTTP_200
            return

        request.context["body"] = request.stream.read()
        try:
            events = json.loads(request.context["body"].decode("utf-8"))["events"]
        except(KeyError, ValueError, UnicodeDecodeError):
            response.status = falcon.HTTP_400
            response.body = "Malformed request body"
            return

        if self.handler(EventStream(events, self.Api)):
            response.status = falcon.HTTP_200
        else:
            response.status = falcon.HTTP_400
index.py 文件源码 项目:ScheduleStorm_Server 作者: Step7750 项目源码 文件源码 阅读 18 收藏 0 点赞 0 评论 0
def on_get(self, req, resp, uni, term):
        # The term must be a string since the threads represent them as such
        if uni in uniThreads and term in uniThreads[uni].getTerms():
            if uniThreads[uni].isScraping:
                # we don't want to return data while scraping, send error (configure nginx to send stale data if it can)
                resp.status = falcon.HTTP_500
                resp.body = json.dumps(
                    {"error": "We're currently scraping this university, please check back in a couple minutes!"}
                ).encode('utf-8')
            else:
                # Get course/subject list
                subject_list = json.dumps(uniThreads[uni].getSubjectListAll(term), sort_keys=True).encode('utf-8')

                # set the etag and body
                resp.etag = "W/" + hashlib.sha1(subject_list).hexdigest()
                resp.body = subject_list
        else:
            # Couldn't find the uni or term, send error
            resp.status = falcon.HTTP_400
            resp.body = json.dumps(
                {"error": "The specified university or term was not found"}
            ).encode('utf-8')
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def login(username, password, response=None):
    """
    Logs user in. Returns status 400 response if user doesn't exist or password is wrong.
    :param username: a username
    :param password: a password
    :return: a token to authenticate with
    """
    if not username or not username.strip():
        logger.debug("Tried to log in with empty username")
        response.status = falcon.HTTP_400
        return "empty username"
    username = username.strip().lower()
    client = _get_client(username)
    if not client:
        logger.debug("Tried to log in with unknown username: %s", username)
        response.status = falcon.HTTP_400
        return "unknown"
    success = bcrypt_sha256.verify(password, client.pw_hash)
    if not success:
        logger.debug("Tried to log in with wrong password as user %s", username)
        response.status = falcon.HTTP_400
        return "wrong password"
    logger.debug("New user login: %s", username)
    return _create_user_token(username, client.permissions)
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 18 收藏 0 点赞 0 评论 0
def suggestions(api_name, max_fetch: hug.types.number = 10, response=None):
    max_fetch = min(10, max(1, max_fetch))

    try:
        api = music_api_names[api_name]
    except KeyError:
        logger.debug("Requested suggestions for unknown API %s", api_name)
        response.status = falcon.HTTP_400
        return "Unknown API"

    if isinstance(api, AbstractSongProvider):
        return list(map(Song.to_json, api.get_suggestions(max_fetch)))
    else:
        logger.debug("Tried to get suggestions for API %s which isn't a SongProvider", api_name)
        response.status = falcon.HTTP_400
        return []
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def get_active_playlist(user: hug.directives.user, response=None):
    """
    Get the active playlist of the offline API.
    :return: the active playlist of the form {'playlist_id': <id>, 'playlist_name': <name>}
    """
    if not has_permission(user, ["admin", "mod", "select_playlist"]):
        response.status = falcon.HTTP_FORBIDDEN
        return "Forbidden"

    try:
        api = music_api_names['offline_api']
        playlist_tuple = api.get_active_playlist()
        if not playlist_tuple:
            return None
        return {'playlist_id': playlist_tuple[0], 'playlist_name': playlist_tuple[1]}
    except KeyError:
        response.status = falcon.HTTP_400
        return "Not in offline mode"
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 18 收藏 0 点赞 0 评论 0
def mark_active(playlist_id: str, user: hug.directives.user, response=None):
    """
    Mark a playlist as active in offline mode.
    Needs admin, mod or select_playlist permission.
    :param playlist_id: the playlist ID as returned by get_available_playlists
    """
    if not has_permission(user, ["admin", "mod", "select_playlist"]):
        response.status = falcon.HTTP_FORBIDDEN
        return "Forbidden"

    try:
        try:
            api = music_api_names['offline_api']
        except KeyError:
            response.status = falcon.HTTP_400
            return "Not in offline mode"
        api.set_active_playlist(playlist_id)
        return "OK"
    except ValueError:
        response.status = falcon.HTTP_UNPROCESSABLE_ENTITY
        return "Unknown ID"
validation.py 文件源码 项目:armada 作者: att-comdev 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def on_post(self, req, resp):
        try:
            manifest = self.req_yaml(req)
            documents = list(manifest)

            message = {
                'valid': validate_armada_documents(documents)
            }

            resp.status = falcon.HTTP_200
            resp.body = json.dumps(message)
            resp.content_type = 'application/json'

        except Exception:
            err_message = 'Failed to validate Armada Manifest'
            self.error(req.context, err_message)
            self.return_error(
                resp, falcon.HTTP_400, message=err_message)
tasks.py 文件源码 项目:drydock 作者: att-comdev 项目源码 文件源码 阅读 28 收藏 0 点赞 0 评论 0
def task_validate_design(self, req, resp, json_data):
        """Create async task for validate design."""
        action = json_data.get('action', None)

        if action != 'validate_design':
            self.error(
                req.context,
                "Task body ended up in wrong handler: action %s in task_validate_design"
                % action)
            self.return_error(
                resp, falcon.HTTP_500, message="Error", retry=False)

        try:
            task = self.create_task(json_data, req.context)
            resp.body = json.dumps(task.to_dict())
            resp.append_header('Location',
                               "/api/v1.0/tasks/%s" % str(task.task_id))
            resp.status = falcon.HTTP_201
        except errors.InvalidFormat as ex:
            self.error(req.context, ex.msg)
            self.return_error(
                resp, falcon.HTTP_400, message=ex.msg, retry=False)
tasks.py 文件源码 项目:drydock 作者: att-comdev 项目源码 文件源码 阅读 33 收藏 0 点赞 0 评论 0
def task_prepare_site(self, req, resp, json_data):
        """Create async task for prepare site."""
        action = json_data.get('action', None)

        if action != 'prepare_site':
            self.error(
                req.context,
                "Task body ended up in wrong handler: action %s in task_prepare_site"
                % action)
            self.return_error(
                resp, falcon.HTTP_500, message="Error", retry=False)

        try:
            task = self.create_task(json_data, req.context)
            resp.body = json.dumps(task.to_dict())
            resp.append_header('Location',
                               "/api/v1.0/tasks/%s" % str(task.task_id))
            resp.status = falcon.HTTP_201
        except errors.InvalidFormat as ex:
            self.error(req.context, ex.msg)
            self.return_error(
                resp, falcon.HTTP_400, message=ex.msg, retry=False)
tasks.py 文件源码 项目:drydock 作者: att-comdev 项目源码 文件源码 阅读 17 收藏 0 点赞 0 评论 0
def task_verify_nodes(self, req, resp, json_data):
        """Create async task for verify node."""
        action = json_data.get('action', None)

        if action != 'verify_nodes':
            self.error(
                req.context,
                "Task body ended up in wrong handler: action %s in task_verify_nodes"
                % action)
            self.return_error(
                resp, falcon.HTTP_500, message="Error", retry=False)

        try:
            task = self.create_task(json_data, req.context)
            resp.body = json.dumps(task.to_dict())
            resp.append_header('Location',
                               "/api/v1.0/tasks/%s" % str(task.task_id))
            resp.status = falcon.HTTP_201
        except errors.InvalidFormat as ex:
            self.error(req.context, ex.msg)
            self.return_error(
                resp, falcon.HTTP_400, message=ex.msg, retry=False)
tasks.py 文件源码 项目:drydock 作者: att-comdev 项目源码 文件源码 阅读 20 收藏 0 点赞 0 评论 0
def task_prepare_nodes(self, req, resp, json_data):
        """Create async task for prepare node."""
        action = json_data.get('action', None)

        if action != 'prepare_nodes':
            self.error(
                req.context,
                "Task body ended up in wrong handler: action %s in task_prepare_nodes"
                % action)
            self.return_error(
                resp, falcon.HTTP_500, message="Error", retry=False)

        try:
            task = self.create_task(json_data, req.context)
            resp.body = json.dumps(task.to_dict())
            resp.append_header('Location',
                               "/api/v1.0/tasks/%s" % str(task.task_id))
            resp.status = falcon.HTTP_201
        except errors.InvalidFormat as ex:
            self.error(req.context, ex.msg)
            self.return_error(
                resp, falcon.HTTP_400, message=ex.msg, retry=False)
tasks.py 文件源码 项目:drydock 作者: att-comdev 项目源码 文件源码 阅读 19 收藏 0 点赞 0 评论 0
def task_deploy_nodes(self, req, resp, json_data):
        """Create async task for deploy node."""
        action = json_data.get('action', None)

        if action != 'deploy_nodes':
            self.error(
                req.context,
                "Task body ended up in wrong handler: action %s in task_deploy_nodes"
                % action)
            self.return_error(
                resp, falcon.HTTP_500, message="Error", retry=False)

        try:
            task = self.create_task(json_data, req.context)
            resp.body = json.dumps(task.to_dict())
            resp.append_header('Location',
                               "/api/v1.0/tasks/%s" % str(task.task_id))
            resp.status = falcon.HTTP_201
        except errors.InvalidFormat as ex:
            self.error(req.context, ex.msg)
            self.return_error(
                resp, falcon.HTTP_400, message=ex.msg, retry=False)
tasks.py 文件源码 项目:drydock 作者: att-comdev 项目源码 文件源码 阅读 23 收藏 0 点赞 0 评论 0
def task_destroy_nodes(self, req, resp, json_data):
        """Create async task for destroy node."""
        action = json_data.get('action', None)

        if action != 'destroy_nodes':
            self.error(
                req.context,
                "Task body ended up in wrong handler: action %s in task_destroy_nodes"
                % action)
            self.return_error(
                resp, falcon.HTTP_500, message="Error", retry=False)

        try:
            task = self.create_task(json_data, req.context)
            resp.body = json.dumps(task.to_dict())
            resp.append_header('Location',
                               "/api/v1.0/tasks/%s" % str(task.task_id))
            resp.status = falcon.HTTP_201
        except errors.InvalidFormat as ex:
            self.error(req.context, ex.msg)
            self.return_error(
                resp, falcon.HTTP_400, message=ex.msg, retry=False)
caffe_model_resource.py 文件源码 项目:Cuppa 作者: flipkart-incubator 项目源码 文件源码 阅读 19 收藏 0 点赞 0 评论 0
def on_post(self, req, resp):
        payload = json.loads(req.stream.read())
        pi = PredictionInput()
        if ('url' in payload.keys()) and ('modelId' in payload.keys()):
            pi.url = payload['url']
            pi.model_id = payload['modelId']
        else:
            resp.status = falcon.HTTP_400
            raise falcon.HTTPBadRequest("Bad Request", "Url and(or) modelId missing in the payload")

        po = self.caffe_worker_client.predict(pi)

        if po.bo.status == 'Success':
            resp.status = falcon.HTTP_200
            resp.body = (str(po.values))
        elif po.bo.status == 'Failure':
            resp.body = json.dumps({'status': 'Failure', 'message' : 'Error occurred'})
            resp.status = falcon.HTTP_500
            raise falcon.HTTPInternalServerError('Internal Server Error', 'Predict failed! ')
zenhttp_falcon.py 文件源码 项目:zenchmarks 作者: squeaky-pl 项目源码 文件源码 阅读 18 收藏 0 点赞 0 评论 0
def on_get(self, req, resp):
        q = req.get_param('q')

        resp.content_type = 'text/plain; charset=utf-8'

        if not q:
            resp.body = 'Bad Request'
            resp.status = falcon.HTTP_400
            return

        try:
            zenline = zenlines[q]
        except KeyError:
            resp.body = 'Not Found'
            resp.status = falcon.HTTP_404
            return

        resp.body = zenline
        resp.status = falcon.HTTP_200
test_wsgi.py 文件源码 项目:CAL 作者: HPCC-Cloud-Computing 项目源码 文件源码 阅读 28 收藏 0 点赞 0 评论 0
def test_process_request_failed_request_no_body(self):
        bad_headers = {
            'Content-Length': '0',
            'Content-Type': 'application/json',
            'URL-METHODS': 'POST, GET, PUT',
        }

        result = self.simulate_post(headers=bad_headers)
        self.assertEqual(falcon.HTTP_400, result.status)
test_wsgi.py 文件源码 项目:CAL 作者: HPCC-Cloud-Computing 项目源码 文件源码 阅读 21 收藏 0 点赞 0 评论 0
def test_process_request_failed_request_MalformedJSON(self):
        headers = {
            'Content-Type': 'application/json',
            'URL-METHODS': 'POST, GET, PUT',
        }

        bad_body = '{"cloud":"cloud1"'
        result = self.simulate_post(headers=headers, body=bad_body)
        self.assertEqual(falcon.HTTP_400, result.status)
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 20 收藏 0 点赞 0 评论 0
def queue(body, remove: hug.types.boolean = False, user: hug.directives.user = None, response=None):
    try:
        song = Song.from_json(body, music_api_names)
        song.user = user['name']
    except ValueError as e:
        logger.debug("Received bad json %s", e)
        response.status = falcon.HTTP_400
        return str(e)

    def _remove():
        try:
            logger.debug("Song %s removed by %s", song, user['name'])
            queue.remove(song)
        except ValueError:
            logger.debug("%s tried to remove Song not in queue: %s", user['name'], song)
            response.status = falcon.HTTP_400
            return "song {} is not in queue".format(song)

    if remove:
        if not has_permission(user, ["admin", "mod", "queue_remove"]):
            try:
                queue_song = queue[queue.index(song)]
                if queue_song.user == user['name']:
                    logger.debug("User %s removes own song %s", user['name'], song)
                    _remove()
                    return "OK"
            except (ValueError, IndexError):
                pass
            logger.debug("Unauthorized attempt to remove song from queue by %s", user['name'])
            response.status = falcon.HTTP_FORBIDDEN
            return "Not permitted"
        _remove()
    else:
        logger.debug("Song %s added by %s", song, user['name'])
        queue.append(song)
    return "OK"
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 19 收藏 0 点赞 0 评论 0
def search(api_name, query, max_fetch: hug.types.number = 50, response=None):
    max_fetch = min(50, max(1, max_fetch))
    try:
        api = music_api_names[api_name]
    except KeyError:
        logger.debug("Tried to search on unknown API %s", api_name)
        response.status = falcon.HTTP_400
        return "Unknown API"

    if not query:
        response.status = falcon.HTTP_400
        return "Invalid query"

    return list(map(Song.to_json, api.search_song(query, max_fetch=max_fetch)))
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 16 收藏 0 点赞 0 评论 0
def move(moving_song_json, other_song_json, after_other: hug.types.boolean = False, user: hug.directives.user = None,
         response=None):
    """
    Move a song before or after another one.
    Needs mod permission.
    :param moving_song_json: the song to move
    :param other_song_json: the song to move before/after
    :param after_other: whether to move after the other song. Passing anything will be evaluated to true.
    """
    if not has_permission(user, ['admin', 'mod']):
        logger.debug("%s tried to move a song, but isn't allowed to.", user['name'])
        response.status = falcon.HTTP_FORBIDDEN
        return "Not a mod"

    try:
        moving_song = Song.from_json(moving_song_json, music_api_names)
        other_song = Song.from_json(other_song_json, music_api_names)
    except ValueError as e:
        logger.debug("Received invalid json (%s): %s , %s", str(e), moving_song_json, other_song_json)
        response.status = falcon.HTTP_400
        return str(e)

    try:
        queue.remove(moving_song)
    except ValueError:
        logger.debug("Tried to move song %s that wasn't in the queue", moving_song)
        response.status = falcon.HTTP_400
        return "song {} is not in queue".format(moving_song)

    try:
        index = queue.index(other_song)
        if after_other:
            index += 1
        queue.insert(index, moving_song)
        logger.debug("Moved song %s after/before(%s) %s", moving_song, after_other, other_song)
        return player_state()
    except ValueError:
        logger.debug("Couldn't move song %s, because other song %s was removed from queue", moving_song, other_song)
        response.status = falcon.HTTP_400
        return "song {} is not in queue".format(other_song)
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 20 收藏 0 点赞 0 评论 0
def grant_permission(target_username, body, user: hug.directives.user = None, response=None):
    """
    Grant a permission to a user
    Note that the new permissions only apply after the user logged out and in again.
    Needs admin permission.
    :param target_username: the username of the user the permission should be granted
    :param body: the permission as returned by get_permissions
    :return: 'OK', error message or None
    """
    try:
        permission = _Permission.from_json(body)
    except ValueError:
        response.status = falcon.HTTP_UNPROCESSABLE_ENTITY
        return "invalid JSON"
    if not is_admin(user):
        logger.debug("%s tried to grant a permission %s to %s but is not admin.", user['name'], permission,
                     target_username)
        response.status = falcon.HTTP_FORBIDDEN
        return None
    target_username = target_username.strip().lower()
    client = _get_client(target_username)
    if not client:
        logger.debug("%s tried to grant permission to unknown user %s", user['name'], target_username)
        response.status = falcon.HTTP_400
        return "unknown target user"
    permissions = client.permissions
    permissions.append(permission.name)
    permissions = list(set(permissions))
    db = _get_db_conn()
    try:
        with db:
            db.execute("UPDATE clients SET permissions=? WHERE username=?", [",".join(permissions), target_username])
    finally:
        db.close()
    return "OK"
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 21 收藏 0 点赞 0 评论 0
def revoke_permission(target_username, body, user: hug.directives.user = None, response=None):
    """
    Revokes a granted permission.
    Note that the new permissions only apply after the user logged out and in again.
    Needs admin permission.
    :param target_username: the username of the user whos permission should be revoked
    :param body: the permission as returned by get_permissions
    :return: 'OK' or error_message or None
    """
    try:
        permission = _Permission.from_json(body)
    except ValueError:
        response.status = falcon.HTTP_UNPROCESSABLE_ENTITY
        return "invalid JSON"
    if not is_admin(user):
        logger.debug("%s tried to revoke a permission %s from %s but is not admin.", user['name'], permission,
                     target_username)
        response.status = falcon.HTTP_FORBIDDEN
        return None
    target_username = target_username.strip().lower()
    client = _get_client(target_username)
    if not client:
        logger.debug("%s tried to revoke permission from unknown user %s", user['name'], target_username)
        response.status = falcon.HTTP_400
        return "unknown target user"
    permissions = client.permissions
    try:
        permissions.remove(permission.name)
    except ValueError:
        pass
    db = _get_db_conn()
    try:
        with db:
            db.execute("UPDATE clients SET permissions=? WHERE username=?", [",".join(permissions), target_username])
    finally:
        db.close()
    return "OK"
rest_api.py 文件源码 项目:MusicBot 作者: BjoernPetersen 项目源码 文件源码 阅读 20 收藏 0 点赞 0 评论 0
def get_available_offline_playlists(user: hug.directives.user, response=None):
    """
    Get all available playlists of the offline API.
    :return: a list of playlists of the form {'playlist_id': <id>, 'playlist_name': <name>}
    """
    if not has_permission(user, ["admin", "mod", "select_playlist"]):
        response.status = falcon.HTTP_FORBIDDEN
        return "Forbidden"
    try:
        api = music_api_names['offline_api']
        playlists = api.get_available_playlists()
        return list(map(lambda p: {'playlist_id': p[0], 'playlist_name': p[1]}, playlists))
    except KeyError:
        response.status = falcon.HTTP_400
        return "Not in offline mode"
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 20 收藏 0 点赞 0 评论 0
def on_patch(self, req, resp):
        raise falcon.HTTPError(falcon.HTTP_400)
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 23 收藏 0 点赞 0 评论 0
def test_no_description_json(self, client):
        response = client.simulate_patch('/fail')
        assert response.status == falcon.HTTP_400
        assert response.json == {'title': '400 Bad Request'}
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 23 收藏 0 点赞 0 评论 0
def test_no_description_xml(self, client):
        response = client.simulate_patch(
            path='/fail', headers={'Accept': 'application/xml'}
        )
        assert response.status == falcon.HTTP_400

        expected_xml = (b'<?xml version="1.0" encoding="UTF-8"?><error>'
                        b'<title>400 Bad Request</title></error>')

        assert response.content == expected_xml
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 22 收藏 0 点赞 0 评论 0
def test_invalid_header(self, client):
        client.app.add_route('/400', InvalidHeaderResource())
        response = client.simulate_request(path='/400')

        expected_desc = (u'The value provided for the X-Auth-Token '
                         u'header is invalid. Please provide a valid token.')

        expected_body = {
            u'title': u'Invalid header value',
            u'description': expected_desc,
            u'code': u'A1001',
        }

        assert response.status == falcon.HTTP_400
        assert response.json == expected_body
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 24 收藏 0 点赞 0 评论 0
def test_missing_header(self, client):
        client.app.add_route('/400', MissingHeaderResource())
        response = client.simulate_request(path='/400')

        expected_body = {
            u'title': u'Missing header value',
            u'description': u'The X-Auth-Token header is required.',
        }

        assert response.status == falcon.HTTP_400
        assert response.json == expected_body
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 19 收藏 0 点赞 0 评论 0
def test_missing_param(self, client):
        client.app.add_route('/400', MissingParamResource())
        response = client.simulate_request(path='/400')

        expected_body = {
            u'title': u'Missing parameter',
            u'description': u'The "id" parameter is required.',
            u'code': u'P1003',
        }

        assert response.status == falcon.HTTP_400
        assert response.json == expected_body
test_httperror.py 文件源码 项目:deb-python-falcon 作者: openstack 项目源码 文件源码 阅读 26 收藏 0 点赞 0 评论 0
def test_misc(self, client):
        self._misc_test(client, falcon.HTTPBadRequest, falcon.HTTP_400)
        self._misc_test(client, falcon.HTTPNotAcceptable, falcon.HTTP_406,
                        needs_title=False)
        self._misc_test(client, falcon.HTTPConflict, falcon.HTTP_409)
        self._misc_test(client, falcon.HTTPPreconditionFailed, falcon.HTTP_412)
        self._misc_test(client, falcon.HTTPUnsupportedMediaType, falcon.HTTP_415,
                        needs_title=False)
        self._misc_test(client, falcon.HTTPUnprocessableEntity, falcon.HTTP_422)
        self._misc_test(client, falcon.HTTPUnavailableForLegalReasons, falcon.HTTP_451,
                        needs_title=False)
        self._misc_test(client, falcon.HTTPInternalServerError, falcon.HTTP_500)
        self._misc_test(client, falcon.HTTPBadGateway, falcon.HTTP_502)


问题


面经


文章

微信
公众号

扫码关注公众号