def post(self) -> None: # type: ignore """POST handler for the 'web' side of things.""" expiry = self.get_body_argument("expiry") if expiry not in utility.expiries: log.info( "CreateAction.post: a paste was submitted with an invalid expiry" ) raise error.ValidationError() auto_scale = self.get_body_argument("long", None) is None lexers = self.get_body_arguments("lexer") raws = self.get_body_arguments("raw", strip=False) filenames = self.get_body_arguments("filename") if not all([lexers, raws, filenames]): # Prevent empty argument lists from making it through raise error.ValidationError() if not all(raw.strip() for raw in raws): # Prevent empty raws from making it through raise error.ValidationError() with database.session() as session: paste = database.Paste(utility.expiries[expiry], "web", auto_scale) if any(len(L) != len(lexers) for L in [lexers, raws, filenames]): log.info("CreateAction.post: mismatching argument lists") raise error.ValidationError() for (lexer, raw, filename) in zip(lexers, raws, filenames): if lexer == 'AUTO': try: lexer = guess_lexer(raw).name except ValueError: # Fall back to plain text lexer = "text" if lexer not in utility.list_languages(): log.info("CreateAction.post: a file had an invalid lexer") raise error.ValidationError() if not raw: log.info("CreateAction.post: a file had an empty raw") raise error.ValidationError() paste.files.append( database.File(raw, lexer, filename if filename else None, auto_scale)) # For the first file we will always use the same slug as the paste, # since slugs are generated to be unique over both pastes and files # this can be done safely. paste.files[0].slug = paste.slug session.add(paste) session.commit() # The removal cookie is set for the specific path of the paste it is # related to self.set_cookie("removal", str(paste.removal), path=f"/{paste.slug}") # Send the client to the paste self.redirect(f"/{paste.slug}")
async def get(self) -> None: self.write(utility.list_languages())
def test_api_get_lexers(self) -> None: response = self.fetch("/json/lexers", method="GET") assert response.code == 200 assert json.loads(response.body) == utility.list_languages()
async def post(self) -> None: if defensive.ratelimit(self.request, area="create"): raise error.RatelimitError() try: data = tornado.escape.json_decode(self.request.body) except json.decoder.JSONDecodeError: raise tornado.web.HTTPError(400, "could not parse json body") expiry = data.get("expiry") if expiry not in configuration.expiries: log.info( "Paste.post: a paste was submitted with an invalid expiry") raise tornado.web.HTTPError(400, "invalid expiry") auto_scale = data.get("long", None) is None files = data.get("files", []) if not files: raise tornado.web.HTTPError(400, "no files provided") with database.session() as session, utility.SlugContext( auto_scale) as slug_context: paste = database.Paste( next(slug_context), configuration.expiries[expiry], "v1-api", ) for file in files: lexer = file.get("lexer", "") content = file.get("content") filename = file.get("name") if lexer not in utility.list_languages(): raise tornado.web.HTTPError(400, "invalid lexer") if not content: raise tornado.web.HTTPError(400, "invalid content (empty)") try: paste.files.append( database.File( next(slug_context), content, lexer, filename, )) except error.ValidationError: raise tornado.web.HTTPError( 400, "invalid content (exceeds size limit)") if sum(len(f.fmt) for f in paste.files) > configuration.paste_size: raise tornado.web.HTTPError( 400, "invalid content (exceeds size limit)") paste.files[0].slug = paste.slug session.add(paste) try: session.commit() except Exception: # XXX be more precise log.warning("%r", slug_context._slugs) raise # Send the client to the paste url_request = self.request.full_url() url_paste = urljoin(url_request, f"/{paste.slug}") url_removal = urljoin(url_request, f"/remove/{paste.removal}") self.write({"link": url_paste, "removal": url_removal})
async def get(self) -> None: if defensive.ratelimit(self.request, area="read"): raise error.RatelimitError() self.write(utility.list_languages())
def post(self) -> None: # type: ignore """POST handler for the 'web' side of things.""" expiry = self.get_body_argument("expiry") if expiry not in configuration.expiries: log.info( "CreateAction.post: a paste was submitted with an invalid expiry" ) raise error.ValidationError() auto_scale = self.get_body_argument("long", None) is None lexers = self.get_body_arguments("lexer") raws = self.get_body_arguments("raw", strip=False) filenames = self.get_body_arguments("filename") if not all([lexers, raws, filenames]): # Prevent empty argument lists from making it through raise error.ValidationError() if not all(raw.strip() for raw in raws): # Prevent empty raws from making it through raise error.ValidationError() if any(len(L) != len(lexers) for L in [lexers, raws, filenames]): log.info("CreateAction.post: mismatching argument lists") raise error.ValidationError() if any(lexer not in utility.list_languages() for lexer in lexers): log.info("CreateAction.post: a file had an invalid lexer") raise error.ValidationError() with database.session() as session, utility.SlugContext( auto_scale ) as slug_context: paste = database.Paste( next(slug_context), configuration.expiries[expiry], "web" ) for (lexer, raw, filename) in zip(lexers, raws, filenames): paste.files.append( database.File( next(slug_context), raw, lexer, filename if filename else None, ) ) if sum(len(f.fmt) for f in paste.files) > configuration.paste_size: log.info("CreateAction.post: sum of files was too large") raise error.ValidationError() # For the first file we will always use the same slug as the paste, # since slugs are generated to be unique over both pastes and files # this can be done safely. paste.files[0].slug = paste.slug session.add(paste) session.commit() # The removal cookie is set for the specific path of the paste it is # related to self.set_cookie( "removal", str(paste.removal), path=f"/{paste.slug}" ) # Send the client to the paste self.redirect(f"/{paste.slug}")