]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
emit more specific status codes on video upload (#3423)
authorRigel Kent <sendmemail@rigelk.eu>
Tue, 8 Dec 2020 20:16:10 +0000 (21:16 +0100)
committerGitHub <noreply@github.com>
Tue, 8 Dec 2020 20:16:10 +0000 (21:16 +0100)
- reduce http status codes list to potentially useful codes
- convert more codes to typed ones
- factorize html generator for error responses

53 files changed:
client/src/app/+about/about-instance/contact-admin-modal.component.ts
client/src/app/+accounts/accounts.component.ts
client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
client/src/app/+video-channels/video-channels.component.ts
client/src/app/+videos/+video-edit/video-add-components/video-upload.component.ts
client/src/app/+videos/+video-watch/video-watch.component.ts
client/src/app/core/auth/auth.service.ts
client/src/app/core/rest/rest-extractor.service.ts
client/src/standalone/videos/embed.ts
server/controllers/client.ts
server/controllers/static.ts
server/helpers/custom-validators/misc.ts
server/helpers/custom-validators/videos.ts
server/helpers/youtube-dl.ts
server/lib/activitypub/actor.ts
server/lib/activitypub/playlist.ts
server/lib/activitypub/videos.ts
server/lib/client-html.ts
server/middlewares/cache.ts
server/middlewares/validators/videos/videos.ts
server/tests/api/activitypub/client.ts
server/tests/api/activitypub/refresher.ts
server/tests/api/check-params/accounts.ts
server/tests/api/check-params/contact-form.ts
server/tests/api/check-params/users.ts
server/tests/api/check-params/videos.ts
server/tests/api/live/live-save-replay.ts
server/tests/api/live/live.ts
server/tests/api/server/config.ts
server/tests/api/server/contact-form.ts
server/tests/api/server/email.ts
server/tests/api/server/follow-constraints.ts
server/tests/api/server/handle-down.ts
server/tests/api/server/no-client.ts
server/tests/api/server/reverse-proxy.ts
server/tests/api/videos/multiple-servers.ts
server/tests/api/videos/video-change-ownership.ts
server/tests/api/videos/video-hls.ts
server/tests/api/videos/video-playlists.ts
server/tests/api/videos/video-privacy.ts
server/tests/api/videos/videos-history.ts
server/tests/cli/reset-password.ts
server/tests/feeds/feeds.ts
server/tests/plugins/filter-hooks.ts
server/tests/plugins/video-constants.ts
server/tools/peertube-redundancy.ts
shared/core-utils/miscs/http-error-codes.ts
shared/extra-utils/server/activitypub.ts
shared/extra-utils/server/redundancy.ts
shared/extra-utils/users/login.ts
shared/extra-utils/videos/video-history.ts
shared/extra-utils/videos/videos.ts
support/doc/api/openapi.yaml

index 11e442f6bc0ca7d8cf308e0f484c890f0ce5ed08..ac2a6c98029f4c958e29a5484071483e9647bcec 100644 (file)
@@ -10,6 +10,7 @@ import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
 import { InstanceService } from '@app/shared/shared-instance'
 import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
 import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 import { ServerConfig } from '@shared/models'
 
 @Component({
@@ -78,7 +79,7 @@ export class ContactAdminModalComponent extends FormReactive implements OnInit {
           },
 
           err => {
-            this.error = err.status === 403
+            this.error = err.status === HttpStatusCode.FORBIDDEN_403
               ? $localize`You already sent this form recently`
               : err.message
           }
index dbc7c888776c053d52e7039d84b4ec14bc4e79f3..4820eaf3253d56b9b08ad02621f085706b941afa 100644 (file)
@@ -6,6 +6,7 @@ import { AuthService, Notifier, RedirectService, RestExtractor, ScreenService, U
 import { Account, AccountService, DropdownAction, ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
 import { AccountReportComponent } from '@app/shared/shared-moderation'
 import { User, UserRight } from '@shared/models'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 @Component({
   templateUrl: './accounts.component.html',
@@ -47,7 +48,10 @@ export class AccountsComponent implements OnInit, OnDestroy {
                           switchMap(accountId => this.accountService.getAccount(accountId)),
                           tap(account => this.onAccount(account)),
                           switchMap(account => this.videoChannelService.listAccountVideoChannels(account)),
-                          catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))
+                          catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
+                            HttpStatusCode.BAD_REQUEST_400,
+                            HttpStatusCode.NOT_FOUND_404
+                          ]))
                         )
                         .subscribe(
                           videoChannels => this.videoChannels = videoChannels.data,
index 1d0cbf24631f2f0b34fa236012c59eef8885fb5c..a625493de5bcb39dcf5690f13cae79a688f97a32 100644 (file)
@@ -10,6 +10,7 @@ import {
 import { FormValidatorService } from '@app/shared/shared-forms'
 import { VideoChannelService } from '@app/shared/shared-main'
 import { VideoChannelCreate } from '@shared/models'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 import { MyVideoChannelEdit } from './my-video-channel-edit'
 
 @Component({
@@ -58,7 +59,7 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
       },
 
       err => {
-        if (err.status === 409) {
+        if (err.status === HttpStatusCode.CONFLICT_409) {
           this.error = $localize`This name already exists on this instance.`
           return
         }
index ea8bda1cf7df5c22653d24e44438e338132d462f..d2fd265c4a7d300ede2e794296458217b2afac62 100644 (file)
@@ -6,6 +6,7 @@ import { ActivatedRoute } from '@angular/router'
 import { AuthService, Notifier, RestExtractor, ScreenService } from '@app/core'
 import { ListOverflowItem, VideoChannel, VideoChannelService } from '@app/shared/shared-main'
 import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 @Component({
   templateUrl: './video-channels.component.html',
@@ -37,7 +38,10 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
                           map(params => params[ 'videoChannelName' ]),
                           distinctUntilChanged(),
                           switchMap(videoChannelName => this.videoChannelService.getVideoChannel(videoChannelName)),
-                          catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 404 ]))
+                          catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
+                            HttpStatusCode.BAD_REQUEST_400,
+                            HttpStatusCode.NOT_FOUND_404
+                          ]))
                         )
                         .subscribe(videoChannel => {
                           this.videoChannel = videoChannel
index bee3679f7480b46e57f7b6954be9bc536d0459ce..cafb030b9930074467a1fed1ee228b254dd59352 100644 (file)
@@ -9,6 +9,7 @@ import { BytesPipe, VideoCaptionService, VideoEdit, VideoService } from '@app/sh
 import { LoadingBarService } from '@ngx-loading-bar/core'
 import { VideoPrivacy } from '@shared/models'
 import { VideoSend } from './video-send'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 @Component({
   selector: 'my-video-upload',
@@ -129,17 +130,17 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
   cancelUpload () {
     if (this.videoUploadObservable !== null) {
       this.videoUploadObservable.unsubscribe()
+    }
 
-      this.isUploadingVideo = false
-      this.videoUploadPercents = 0
-      this.videoUploadObservable = null
+    this.isUploadingVideo = false
+    this.videoUploadPercents = 0
+    this.videoUploadObservable = null
 
-      this.firstStepError.emit()
-      this.enableRetryAfterError = false
-      this.error = ''
+    this.firstStepError.emit()
+    this.enableRetryAfterError = false
+    this.error = ''
 
-      this.notifier.info($localize`Upload cancelled`)
-    }
+    this.notifier.info($localize`Upload cancelled`)
   }
 
   uploadFirstStep (clickedOnButton = false) {
@@ -229,6 +230,11 @@ export class VideoUploadComponent extends VideoSend implements OnInit, OnDestroy
           notifier: this.notifier,
           sticky: false
         })
+
+        if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413 ||
+            err.status === HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415) {
+          this.cancelUpload()
+        }
       }
     )
   }
index b15de2a79633922f5f030097a5bddf32d4292523..33de901c02f9a24c4d42368e706d63ecf33fce35 100644 (file)
@@ -39,6 +39,7 @@ import { isWebRTCDisabled, timeToInt } from '../../../assets/player/utils'
 import { environment } from '../../../environments/environment'
 import { VideoSupportComponent } from './modal/video-support.component'
 import { VideoWatchPlaylistComponent } from './video-watch-playlist.component'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 type URLOptions = CustomizationOptions & { playerMode: PlayerMode }
 
@@ -412,13 +413,25 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
               $localize`This video is not available on this instance. Do you want to be redirected on the origin instance: <a href="${originUrl}">${originUrl}</a>?`,
               $localize`Redirection`
             ).then(res => {
-              if (res === false) return this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ])
+              if (res === false) {
+                return this.restExtractor.redirectTo404IfNotFound(err, [
+                  HttpStatusCode.BAD_REQUEST_400,
+                  HttpStatusCode.UNAUTHORIZED_401,
+                  HttpStatusCode.FORBIDDEN_403,
+                  HttpStatusCode.NOT_FOUND_404
+                ])
+              }
 
               return window.location.href = originUrl
             })
           }
 
-          return this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ])
+          return this.restExtractor.redirectTo404IfNotFound(err, [
+            HttpStatusCode.BAD_REQUEST_400,
+            HttpStatusCode.UNAUTHORIZED_401,
+            HttpStatusCode.FORBIDDEN_403,
+            HttpStatusCode.NOT_FOUND_404
+          ])
         })
       )
       .subscribe(([ video, captionsResult ]) => {
@@ -450,7 +463,12 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     this.playlistService.getVideoPlaylist(playlistId)
       .pipe(
         // If 401, the video is private or blocked so redirect to 404
-        catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [ 400, 401, 403, 404 ]))
+        catchError(err => this.restExtractor.redirectTo404IfNotFound(err, [
+          HttpStatusCode.BAD_REQUEST_400,
+          HttpStatusCode.UNAUTHORIZED_401,
+          HttpStatusCode.FORBIDDEN_403,
+          HttpStatusCode.NOT_FOUND_404
+        ]))
       )
       .subscribe(playlist => {
         this.playlist = playlist
index fd6062d3fbdb864aecbc0398f12c5803235f65a6..cdf13186b68f3338dc49ba687f0eed411c1bf0f8 100644 (file)
@@ -11,6 +11,7 @@ import { environment } from '../../../environments/environment'
 import { RestExtractor } from '../rest/rest-extractor.service'
 import { AuthStatus } from './auth-status.model'
 import { AuthUser } from './auth-user.model'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 interface UserLoginWithUsername extends UserLogin {
   access_token: string
@@ -94,7 +95,7 @@ export class AuthService {
           error => {
             let errorMessage = error.message
 
-            if (error.status === 403) {
+            if (error.status === HttpStatusCode.FORBIDDEN_403) {
               errorMessage = $localize`Cannot retrieve OAuth Client credentials: ${error.text}.
 Ensure you have correctly configured PeerTube (config/ directory), in particular the "webserver" section.`
             }
index 4b8c1e1555579567de687f068487568185eb6e88..84d9ed074d4580b1348b6b2a262f6a9dba9af6cb 100644 (file)
@@ -3,6 +3,7 @@ import { Injectable } from '@angular/core'
 import { Router } from '@angular/router'
 import { dateToHuman } from '@app/helpers'
 import { ResultList } from '@shared/models'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 @Injectable()
 export class RestExtractor {
@@ -57,9 +58,9 @@ export class RestExtractor {
         errorMessage = errorsArray.join('. ')
       } else if (err.error && err.error.error) {
         errorMessage = err.error.error
-      } else if (err.status === 413) {
+      } else if (err.status === HttpStatusCode.PAYLOAD_TOO_LARGE_413) {
         errorMessage = $localize`Media is too large for the server. Please contact you administrator if you want to increase the limit size.`
-      } else if (err.status === 429) {
+      } else if (err.status === HttpStatusCode.TOO_MANY_REQUESTS_429) {
         const secondsLeft = err.headers.get('retry-after')
         if (secondsLeft) {
           const minutesLeft = Math.floor(parseInt(secondsLeft, 10) / 60)
@@ -67,7 +68,7 @@ export class RestExtractor {
         } else {
           errorMessage = $localize`Too many attempts, please try again later.`
         }
-      } else if (err.status === 500) {
+      } else if (err.status === HttpStatusCode.INTERNAL_SERVER_ERROR_500) {
         errorMessage = $localize`Server error. Please retry later.`
       }
 
@@ -92,7 +93,7 @@ export class RestExtractor {
     return observableThrowError(errorObj)
   }
 
-  redirectTo404IfNotFound (obj: { status: number }, status = [ 404 ]) {
+  redirectTo404IfNotFound (obj: { status: number }, status = [ HttpStatusCode.NOT_FOUND_404 ]) {
     if (obj && obj.status && status.indexOf(obj.status) !== -1) {
       // Do not use redirectService to avoid circular dependencies
       this.router.navigate([ '/404' ], { skipLocationChange: true })
index 48f7e77490687f711cee76be412c81b0e72ce153..1709d44e7a7cbde0afacfa80e992e080847d4446 100644 (file)
@@ -13,6 +13,7 @@ import {
   PluginType,
   ClientHookName
 } from '../../../../shared/models'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 import { P2PMediaLoaderOptions, PeertubePlayerManagerOptions, PlayerMode } from '../../assets/player/peertube-player-manager'
 import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
 import { TranslationsManager } from '../../assets/player/translations-manager'
@@ -85,7 +86,7 @@ export class PeerTubeEmbed {
   refreshFetch (url: string, options?: RequestInit) {
     return fetch(url, options)
       .then((res: Response) => {
-        if (res.status !== 401) return res
+        if (res.status !== HttpStatusCode.UNAUTHORIZED_401) return res
 
         const refreshingTokenPromise = new Promise((resolve, reject) => {
           const clientId: string = peertubeLocalStorage.getItem(this.LOCAL_STORAGE_OAUTH_CLIENT_KEYS.CLIENT_ID)
@@ -107,7 +108,7 @@ export class PeerTubeEmbed {
             method: 'POST',
             body: objectToUrlEncoded(data)
           }).then(res => {
-            if (res.status === 401) return undefined
+            if (res.status === HttpStatusCode.UNAUTHORIZED_401) return undefined
 
             return res.json()
           }).then((obj: UserRefreshToken & { code: 'invalid_grant'}) => {
@@ -338,7 +339,7 @@ export class PeerTubeEmbed {
 
     try {
       playlistResponse = await playlistPromise
-      isResponseOk = playlistResponse.status === 200
+      isResponseOk = playlistResponse.status === HttpStatusCode.OK_200
     } catch (err) {
       console.error(err)
       isResponseOk = false
@@ -347,7 +348,7 @@ export class PeerTubeEmbed {
     if (!isResponseOk) {
       const serverTranslations = await this.translationsPromise
 
-      if (playlistResponse?.status === 404) {
+      if (playlistResponse?.status === HttpStatusCode.NOT_FOUND_404) {
         this.playlistNotFound(serverTranslations)
         return undefined
       }
@@ -367,7 +368,7 @@ export class PeerTubeEmbed {
 
     try {
       videoResponse = await videoPromise
-      isResponseOk = videoResponse.status === 200
+      isResponseOk = videoResponse.status === HttpStatusCode.OK_200
     } catch (err) {
       console.error(err)
 
@@ -377,7 +378,7 @@ export class PeerTubeEmbed {
     if (!isResponseOk) {
       const serverTranslations = await this.translationsPromise
 
-      if (videoResponse?.status === 404) {
+      if (videoResponse?.status === HttpStatusCode.NOT_FOUND_404) {
         this.videoNotFound(serverTranslations)
         return undefined
       }
index 49e6fd66132e96d123587a526ca2cda251e3c219..bd1f19f8c913ab30a83a69c4d51be06311cd0459 100644 (file)
@@ -3,12 +3,11 @@ import { constants, promises as fs } from 'fs'
 import { join } from 'path'
 import { CONFIG } from '@server/initializers/config'
 import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '@shared/core-utils/i18n'
+import { HttpStatusCode } from '@shared/core-utils'
 import { root } from '../helpers/core-utils'
-import { logger } from '../helpers/logger'
-import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers/constants'
-import { ClientHtml } from '../lib/client-html'
+import { STATIC_MAX_AGE } from '../initializers/constants'
+import { ClientHtml, sendHTML, serveIndexHTML } from '../lib/client-html'
 import { asyncMiddleware, embedCSP } from '../middlewares'
-import { HttpStatusCode } from '@shared/core-utils'
 
 const clientsRouter = express.Router()
 
@@ -118,31 +117,12 @@ function serveServerTranslations (req: express.Request, res: express.Response) {
   return res.sendStatus(HttpStatusCode.NOT_FOUND_404)
 }
 
-async function serveIndexHTML (req: express.Request, res: express.Response) {
-  if (req.accepts(ACCEPT_HEADERS) === 'html') {
-    try {
-      await generateHTMLPage(req, res, req.params.language)
-      return
-    } catch (err) {
-      logger.error('Cannot generate HTML page.', err)
-    }
-  }
-
-  return res.status(HttpStatusCode.INTERNAL_SERVER_ERROR_500).end()
-}
-
 async function generateEmbedHtmlPage (req: express.Request, res: express.Response) {
   const html = await ClientHtml.getEmbedHTML()
 
   return sendHTML(html, res)
 }
 
-async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
-  const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
-
-  return sendHTML(html, res)
-}
-
 async function generateWatchHtmlPage (req: express.Request, res: express.Response) {
   const html = await ClientHtml.getWatchHTMLPage(req.params.id + '', req, res)
 
@@ -167,12 +147,6 @@ async function generateVideoChannelHtmlPage (req: express.Request, res: express.
   return sendHTML(html, res)
 }
 
-function sendHTML (html: string, res: express.Response) {
-  res.set('Content-Type', 'text/html; charset=UTF-8')
-
-  return res.send(html)
-}
-
 async function generateManifest (req: express.Request, res: express.Response) {
   const manifestPhysicalPath = join(root(), 'client', 'dist', 'manifest.webmanifest')
   const manifestJson = await fs.readFile(manifestPhysicalPath, 'utf8')
index ff77452ddb838f58b8714d43a48aa96ab795e0c8..f12f00e1bba3fcbf72ecd89a4939c66018513ce7 100644 (file)
@@ -27,6 +27,7 @@ import { getTorrentFilePath, getVideoFilePath } from '@server/lib/video-paths'
 import { getThemeOrDefault } from '../lib/plugins/theme-utils'
 import { getEnabledResolutions, getRegisteredPlugins, getRegisteredThemes } from '@server/controllers/api/config'
 import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
+import { serveIndexHTML } from '@server/lib/client-html'
 
 const staticRouter = express.Router()
 
@@ -119,6 +120,11 @@ staticRouter.get('/robots.txt',
   }
 )
 
+staticRouter.all('/teapot',
+  getCup,
+  asyncMiddleware(serveIndexHTML)
+)
+
 // security.txt service
 staticRouter.get('/security.txt',
   (_, res: express.Response) => {
@@ -391,3 +397,11 @@ function getHLSPlaylist (video: MVideoFullLight) {
 
   return Object.assign(playlist, { Video: video })
 }
+
+function getCup (req: express.Request, res: express.Response, next: express.NextFunction) {
+  res.status(HttpStatusCode.I_AM_A_TEAPOT_418)
+  res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1')
+  res.setHeader('Safe', 'if-sepia-awake')
+
+  return next()
+}
index 61c03f0c978fa947e6494452333fa3496aaade56..effdd98cb9c4b3c8b222138f8e97bbf4c0b80e87 100644 (file)
@@ -86,6 +86,50 @@ function toIntArray (value: any) {
   return value.map(v => validator.toInt(v))
 }
 
+function isFileFieldValid (
+  files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
+  field: string,
+  optional = false
+) {
+  // Should have files
+  if (!files) return optional
+  if (isArray(files)) return optional
+
+  // Should have a file
+  const fileArray = files[field]
+  if (!fileArray || fileArray.length === 0) {
+    return optional
+  }
+
+  // The file should exist
+  const file = fileArray[0]
+  if (!file || !file.originalname) return false
+  return file
+}
+
+function isFileMimeTypeValid (
+  files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
+  mimeTypeRegex: string,
+  field: string,
+  optional = false
+) {
+  // Should have files
+  if (!files) return optional
+  if (isArray(files)) return optional
+
+  // Should have a file
+  const fileArray = files[field]
+  if (!fileArray || fileArray.length === 0) {
+    return optional
+  }
+
+  // The file should exist
+  const file = fileArray[0]
+  if (!file || !file.originalname) return false
+
+  return new RegExp(`^${mimeTypeRegex}$`, 'i').test(file.mimetype)
+}
+
 function isFileValid (
   files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[],
   mimeTypeRegex: string,
@@ -132,5 +176,7 @@ export {
   toIntOrNull,
   toArray,
   toIntArray,
+  isFileFieldValid,
+  isFileMimeTypeValid,
   isFileValid
 }
index 8b309ae42f4b12155ae65e18df2443be8fd605e3..87966798f435b41774fdc18fd42f46dcf1855d2c 100644 (file)
@@ -11,7 +11,7 @@ import {
   VIDEO_STATES,
   VIDEO_LIVE
 } from '../../initializers/constants'
-import { exists, isArray, isDateValid, isFileValid } from './misc'
+import { exists, isArray, isDateValid, isFileMimeTypeValid, isFileValid } from './misc'
 import * as magnetUtil from 'magnet-uri'
 
 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
@@ -81,8 +81,8 @@ function isVideoFileExtnameValid (value: string) {
   return exists(value) && (value === VIDEO_LIVE.EXTENSION || MIMETYPES.VIDEO.EXT_MIMETYPE[value] !== undefined)
 }
 
-function isVideoFile (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
-  return isFileValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile', null)
+function isVideoFileMimeTypeValid (files: { [ fieldname: string ]: Express.Multer.File[] } | Express.Multer.File[]) {
+  return isFileMimeTypeValid(files, MIMETYPES.VIDEO.MIMETYPES_REGEX, 'videofile')
 }
 
 const videoImageTypes = CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME
@@ -143,12 +143,12 @@ export {
   isVideoFPSResolutionValid,
   isScheduleVideoUpdatePrivacyValid,
   isVideoOriginallyPublishedAtValid,
-  isVideoFile,
   isVideoMagnetUriValid,
   isVideoStateValid,
   isVideoViewsValid,
   isVideoRatingTypeValid,
   isVideoFileExtnameValid,
+  isVideoFileMimeTypeValid,
   isVideoDurationValid,
   isVideoTagValid,
   isVideoPrivacyValid,
index 302b2e206bee857848da85177962eaee09121ad0..9e8ef90d8041223bdff0c8b9cd7ec38e8ccd2df3 100644 (file)
@@ -7,6 +7,7 @@ import { ensureDir, remove, writeFile } from 'fs-extra'
 import * as request from 'request'
 import { createWriteStream } from 'fs'
 import { CONFIG } from '@server/initializers/config'
+import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
 
 export type YoutubeDLInfo = {
   name?: string
@@ -154,7 +155,7 @@ async function updateYoutubeDLBinary () {
         return res()
       }
 
-      if (result.statusCode !== 302) {
+      if (result.statusCode !== HttpStatusCode.FOUND_302) {
         logger.error('youtube-dl update error: did not get redirect for the latest version link. Status %d', result.statusCode)
         return res()
       }
@@ -164,7 +165,7 @@ async function updateYoutubeDLBinary () {
       const newVersion = /yt-dl\.org\/downloads\/(\d{4}\.\d\d\.\d\d(\.\d)?)\/youtube-dl/.exec(url)[1]
 
       downloadFile.on('response', result => {
-        if (result.statusCode !== 200) {
+        if (result.statusCode !== HttpStatusCode.OK_200) {
           logger.error('Cannot update youtube-dl: new version response is not 200, it\'s %d.', result.statusCode)
           return res()
         }
index fb5558ff6b7bbc605f891f7fea4db9c8bb7754bc..52547536cfe7db29e4f2450bb3234b55ddce87d4 100644 (file)
@@ -36,6 +36,7 @@ import {
 } from '../../types/models'
 import { extname } from 'path'
 import { getServerActor } from '@server/models/application/application'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 // Set account keys, this could be long so process after the account creation and do not block the client
 function setAsyncActorKeys <T extends MActor> (actor: T) {
@@ -277,7 +278,7 @@ async function refreshActorIfNeeded <T extends MActorFull | MActorAccountChannel
 
     const { result, statusCode } = await fetchRemoteActor(actorUrl)
 
-    if (statusCode === 404) {
+    if (statusCode === HttpStatusCode.NOT_FOUND_404) {
       logger.info('Deleting actor %s because there is a 404 in refresh actor.', actor.url)
       actor.Account
         ? await actor.Account.destroy()
index bd442b22392af14092d6d25fee8f83daf48d7c03..53298e968c1db28cff277da22e83b9285d91af6a 100644 (file)
@@ -18,6 +18,7 @@ import { createPlaylistMiniatureFromUrl } from '../thumbnail'
 import { FilteredModelAttributes } from '../../types/sequelize'
 import { MAccountDefault, MAccountId, MVideoId } from '../../types/models'
 import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) {
   const privacy = to.includes(ACTIVITY_PUB.PUBLIC)
@@ -120,7 +121,7 @@ async function refreshVideoPlaylistIfNeeded (videoPlaylist: MVideoPlaylistOwner)
 
   try {
     const { statusCode, playlistObject } = await fetchRemoteVideoPlaylist(videoPlaylist.url)
-    if (statusCode === 404) {
+    if (statusCode === HttpStatusCode.NOT_FOUND_404) {
       logger.info('Cannot refresh remote video playlist %s: it does not exist anymore. Deleting it.', videoPlaylist.url)
 
       await videoPlaylist.destroy()
index 04f0bfc230e11c8b3f404bee03361e85c9aeab7f..b15d5da1c1862d9fb17ff2626e1d18effca5f551 100644 (file)
@@ -76,6 +76,7 @@ import { sendCreateVideo, sendUpdateVideo } from './send'
 import { addVideoShares, shareVideoByServerAndChannel } from './share'
 import { addVideoComments } from './video-comments'
 import { createRates } from './video-rates'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) {
   const video = videoArg as MVideoAP
@@ -488,7 +489,7 @@ async function refreshVideoIfNeeded (options: {
 
   try {
     const { response, videoObject } = await fetchRemoteVideo(video.url)
-    if (response.statusCode === 404) {
+    if (response.statusCode === HttpStatusCode.NOT_FOUND_404) {
       logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url)
 
       // Video does not exist anymore
index d97d2318017a3696d310aae4aa23e343ce1bda83..32f5d29abbaa968bc40fa9b32f0a94c6db998f0a 100644 (file)
@@ -1,4 +1,5 @@
 import * as express from 'express'
+import * as Bluebird from 'bluebird'
 import { buildFileLocale, getDefaultLocale, is18nLocale, POSSIBLE_LOCALES } from '../../shared/core-utils/i18n/i18n'
 import {
   AVATARS_SIZE,
@@ -6,7 +7,8 @@ import {
   EMBED_SIZE,
   PLUGIN_GLOBAL_CSS_PATH,
   WEBSERVER,
-  FILES_CONTENT_HASH
+  FILES_CONTENT_HASH,
+  ACCEPT_HEADERS
 } from '../initializers/constants'
 import { join } from 'path'
 import { escapeHTML, isTestInstance, sha256 } from '../helpers/core-utils'
@@ -18,7 +20,6 @@ import { readFile } from 'fs-extra'
 import { getActivityStreamDuration } from '../models/video/video-format-utils'
 import { AccountModel } from '../models/account/account'
 import { VideoChannelModel } from '../models/video/video-channel'
-import * as Bluebird from 'bluebird'
 import { CONFIG } from '../initializers/config'
 import { logger } from '../helpers/logger'
 import { MAccountActor, MChannelActor } from '../types/models'
@@ -53,7 +54,7 @@ type Tags = {
   }
 }
 
-export class ClientHtml {
+class ClientHtml {
 
   private static htmlCache: { [path: string]: string } = {}
 
@@ -505,3 +506,38 @@ export class ClientHtml {
     return htmlStringPage.replace(CUSTOM_HTML_TAG_COMMENTS.META_TAGS, tagsString)
   }
 }
+
+function sendHTML (html: string, res: express.Response) {
+  res.set('Content-Type', 'text/html; charset=UTF-8')
+
+  return res.send(html)
+}
+
+async function serveIndexHTML (req: express.Request, res: express.Response) {
+  if (req.accepts(ACCEPT_HEADERS) === 'html' ||
+      !req.headers.accept) {
+    try {
+      await generateHTMLPage(req, res, req.params.language)
+      return
+    } catch (err) {
+      logger.error('Cannot generate HTML page.', err)
+      return res.sendStatus(HttpStatusCode.INTERNAL_SERVER_ERROR_500)
+    }
+  }
+
+  return res.sendStatus(HttpStatusCode.NOT_ACCEPTABLE_406)
+}
+
+// ---------------------------------------------------------------------------
+
+export {
+  ClientHtml,
+  sendHTML,
+  serveIndexHTML
+}
+
+async function generateHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
+  const html = await ClientHtml.getDefaultHTMLPage(req, res, paramLang)
+
+  return sendHTML(html, res)
+}
index cb24d9e0e51698eb317b1c8cdfb9d9c7da38b700..0708ee8e8cc3b353421aa8acd6528b15ea4e1f19 100644 (file)
@@ -1,5 +1,6 @@
 import { Redis } from '../lib/redis'
 import * as apicache from 'apicache'
+import { HttpStatusCode } from '../../shared/core-utils/miscs/http-error-codes'
 
 // Ensure Redis is initialized
 Redis.Instance.init()
@@ -8,7 +9,10 @@ const defaultOptions = {
   redisClient: Redis.Instance.getClient(),
   appendKey: () => Redis.Instance.getPrefix(),
   statusCodes: {
-    exclude: [ 404, 403 ]
+    exclude: [
+      HttpStatusCode.FORBIDDEN_403,
+      HttpStatusCode.NOT_FOUND_404
+    ]
   }
 }
 
index 9834f714bd6cdbd6eb0b7e6b0a46c22e0ba13066..8bc37b0abd84f156815dfa3214b397d67ed13e88 100644 (file)
@@ -8,6 +8,7 @@ import { VideoChangeOwnershipAccept } from '../../../../shared/models/videos/vid
 import {
   isBooleanValid,
   isDateValid,
+  isFileFieldValid,
   isIdOrUUIDValid,
   isIdValid,
   isUUIDValid,
@@ -22,7 +23,8 @@ import {
   isScheduleVideoUpdatePrivacyValid,
   isVideoCategoryValid,
   isVideoDescriptionValid,
-  isVideoFile,
+  isVideoFileMimeTypeValid,
+  isVideoFileSizeValid,
   isVideoFilterValid,
   isVideoImage,
   isVideoLanguageValid,
@@ -55,11 +57,11 @@ import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-c
 
 const videosAddValidator = getCommonVideoEditAttributes().concat([
   body('videofile')
-    .custom((value, { req }) => isVideoFile(req.files)).withMessage(
-      'This file is not supported or too large. Please, make sure it is of the following type: ' +
-      CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
-    ),
-  body('name').custom(isVideoNameValid).withMessage('Should have a valid name'),
+    .custom((value, { req }) => isFileFieldValid(req.files, 'videofile'))
+    .withMessage('Should have a file'),
+  body('name')
+    .custom(isVideoNameValid)
+    .withMessage('Should have a valid name'),
   body('channelId')
     .customSanitizer(toIntOrNull)
     .custom(isIdValid).withMessage('Should have correct video channel id'),
@@ -75,8 +77,27 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
 
     if (!await doesVideoChannelOfAccountExist(req.body.channelId, user, res)) return cleanUpReqFiles(req)
 
+    if (!isVideoFileMimeTypeValid(req.files)) {
+      res.status(HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
+         .json({
+           error: 'This file is not supported. Please, make sure it is of the following type: ' +
+                  CONSTRAINTS_FIELDS.VIDEOS.EXTNAME.join(', ')
+         })
+
+      return cleanUpReqFiles(req)
+    }
+
+    if (!isVideoFileSizeValid(videoFile.size.toString())) {
+      res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
+         .json({
+           error: 'This file is too large.'
+         })
+
+      return cleanUpReqFiles(req)
+    }
+
     if (await isAbleToUploadVideo(user.id, videoFile.size) === false) {
-      res.status(HttpStatusCode.FORBIDDEN_403)
+      res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
          .json({ error: 'The user video quota is exceeded with this video.' })
 
       return cleanUpReqFiles(req)
@@ -88,8 +109,8 @@ const videosAddValidator = getCommonVideoEditAttributes().concat([
       duration = await getDurationFromVideoFile(videoFile.path)
     } catch (err) {
       logger.error('Invalid input file in videosAddValidator.', { err })
-      res.status(HttpStatusCode.BAD_REQUEST_400)
-         .json({ error: 'Invalid input file.' })
+      res.status(HttpStatusCode.UNPROCESSABLE_ENTITY_422)
+         .json({ error: 'Video file unreadable.' })
 
       return cleanUpReqFiles(req)
     }
@@ -295,7 +316,7 @@ const videosAcceptChangeOwnershipValidator = [
     const videoChangeOwnership = res.locals.videoChangeOwnership
     const isAble = await isAbleToUploadVideo(user.id, videoChangeOwnership.Video.getMaxQualityFile().size)
     if (isAble === false) {
-      res.status(HttpStatusCode.FORBIDDEN_403)
+      res.status(HttpStatusCode.PAYLOAD_TOO_LARGE_413)
         .json({ error: 'The user video quota is exceeded with this video.' })
 
       return
index d16f0510803773f6aa51f1ba6b046b5fe01ff906..b6c538e19781a2f1cd445f1cf8cb40056f1ed1cd 100644 (file)
@@ -11,6 +11,7 @@ import {
   setAccessTokensToServers,
   uploadVideo
 } from '../../../../shared/extra-utils'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -53,7 +54,7 @@ describe('Test activitypub', function () {
   })
 
   it('Should redirect to the origin video object', async function () {
-    const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, 302)
+    const res = await makeActivityPubGetRequest(servers[1].url, '/videos/watch/' + videoUUID, HttpStatusCode.FOUND_302)
 
     expect(res.header.location).to.equal('http://localhost:' + servers[0].port + '/videos/watch/' + videoUUID)
   })
index 232c5d82341a75d3754aaea140c3319a3af4edf1..c717f1a307676ce0b0fecd90b43dc9d3aa24df2d 100644 (file)
@@ -24,6 +24,7 @@ import {
 } from '../../../../shared/extra-utils'
 import { getAccount } from '../../../../shared/extra-utils/users/accounts'
 import { VideoPlaylistPrivacy } from '../../../../shared/models/videos'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test AP refresher', function () {
   let servers: ServerInfo[] = []
@@ -86,8 +87,8 @@ describe('Test AP refresher', function () {
 
       await waitJobs(servers)
 
-      await getVideo(servers[0].url, videoUUID1, 404)
-      await getVideo(servers[0].url, videoUUID2, 200)
+      await getVideo(servers[0].url, videoUUID1, HttpStatusCode.NOT_FOUND_404)
+      await getVideo(servers[0].url, videoUUID2, HttpStatusCode.OK_200)
     })
 
     it('Should not update a remote video if the remote instance is down', async function () {
@@ -106,7 +107,7 @@ describe('Test AP refresher', function () {
 
       await reRunServer(servers[1])
 
-      await getVideo(servers[0].url, videoUUID3, 200)
+      await getVideo(servers[0].url, videoUUID3, HttpStatusCode.OK_200)
     })
   })
 
@@ -126,8 +127,8 @@ describe('Test AP refresher', function () {
 
       await waitJobs(servers)
 
-      await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, 200)
-      await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, 404)
+      await getAccount(servers[0].url, 'user1@localhost:' + servers[1].port, HttpStatusCode.OK_200)
+      await getAccount(servers[0].url, 'user2@localhost:' + servers[1].port, HttpStatusCode.NOT_FOUND_404)
     })
   })
 
@@ -146,8 +147,8 @@ describe('Test AP refresher', function () {
 
       await waitJobs(servers)
 
-      await getVideoPlaylist(servers[0].url, playlistUUID1, 200)
-      await getVideoPlaylist(servers[0].url, playlistUUID2, 404)
+      await getVideoPlaylist(servers[0].url, playlistUUID1, HttpStatusCode.OK_200)
+      await getVideoPlaylist(servers[0].url, playlistUUID2, HttpStatusCode.NOT_FOUND_404)
     })
   })
 
index c29af7cd70059b89f0efd87d1fe76ff5949bd774..d1712cff61999ab6f19ee785bede7942b204d4de 100644 (file)
@@ -9,6 +9,7 @@ import {
   checkBadStartPagination
 } from '../../../../shared/extra-utils/requests/check-api-params'
 import { getAccount } from '../../../../shared/extra-utils/users/accounts'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test accounts API validators', function () {
   const path = '/api/v1/accounts/'
@@ -38,7 +39,7 @@ describe('Test accounts API validators', function () {
 
   describe('When getting an account', function () {
     it('Should return 404 with a non existing name', async function () {
-      await getAccount(server.url, 'arfaze', 404)
+      await getAccount(server.url, 'arfaze', HttpStatusCode.NOT_FOUND_404)
     })
   })
 
index b2126b9b09981b7d80771d409a1ea743d86a2f83..c7f9c1b476332aaa6e19b179e09c3bbe94758aec 100644 (file)
@@ -5,6 +5,7 @@ import 'mocha'
 import { cleanupTests, flushAndRunServer, immutableAssign, killallServers, reRunServer, ServerInfo } from '../../../../shared/extra-utils'
 import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
 import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test contact form API validators', function () {
   let server: ServerInfo
@@ -29,7 +30,7 @@ describe('Test contact form API validators', function () {
   })
 
   it('Should not accept a contact form if emails are disabled', async function () {
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 }))
+    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
   })
 
   it('Should not accept a contact form if it is disabled in the configuration', async function () {
@@ -39,7 +40,7 @@ describe('Test contact form API validators', function () {
 
     // Contact form is disabled
     await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort }, contact_form: { enabled: false } })
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 409 }))
+    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: HttpStatusCode.CONFLICT_409 }))
   })
 
   it('Should not accept a contact form if from email is invalid', async function () {
@@ -50,21 +51,57 @@ describe('Test contact form API validators', function () {
     // Email & contact form enabled
     await reRunServer(server, { smtp: { hostname: 'localhost', port: emailPort } })
 
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail' }))
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: 'badEmail@' }))
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromEmail: undefined }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      fromEmail: 'badEmail'
+    }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      fromEmail: 'badEmail@'
+    }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      fromEmail: undefined
+    }))
   })
 
   it('Should not accept a contact form if from name is invalid', async function () {
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: 'name'.repeat(100) }))
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: '' }))
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, fromName: undefined }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      fromName: 'name'.repeat(100)
+    }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      fromName: ''
+    }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      fromName: undefined
+    }))
   })
 
   it('Should not accept a contact form if body is invalid', async function () {
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'body'.repeat(5000) }))
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: 'a' }))
-    await sendContactForm(immutableAssign(defaultBody, { url: server.url, expectedStatus: 400, body: undefined }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      body: 'body'.repeat(5000)
+    }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      body: 'a'
+    }))
+    await sendContactForm(immutableAssign(defaultBody, {
+      url: server.url,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400,
+      body: undefined
+    }))
   })
 
   it('Should accept a contact form with the correct parameters', async function () {
index 21ace36aa573474b138cab5e3ed52081d160d918..0a13f5b678cefc1168b4b4dae95200c37a43c5f3 100644 (file)
@@ -1102,7 +1102,7 @@ describe('Test users API validators', function () {
         videoQuota: 42
       })
 
-      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
+      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
     })
 
     it('Should fail with a registered user having too many videos', async function () {
@@ -1120,7 +1120,7 @@ describe('Test users API validators', function () {
       await uploadVideo(server.url, userAccessToken, videoAttributes)
       await uploadVideo(server.url, userAccessToken, videoAttributes)
       await uploadVideo(server.url, userAccessToken, videoAttributes)
-      await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.FORBIDDEN_403)
+      await uploadVideo(server.url, userAccessToken, videoAttributes, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
     })
 
     it('Should fail to import with HTTP/Torrent/magnet', async function () {
@@ -1151,7 +1151,7 @@ describe('Test users API validators', function () {
   })
 
   describe('When having a daily video quota', function () {
-    it('Should fail with a user having too many videos', async function () {
+    it('Should fail with a user having too many videos daily', async function () {
       await updateUser({
         url: server.url,
         userId: rootId,
@@ -1159,7 +1159,7 @@ describe('Test users API validators', function () {
         videoQuotaDaily: 42
       })
 
-      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
+      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
     })
   })
 
@@ -1173,7 +1173,7 @@ describe('Test users API validators', function () {
         videoQuotaDaily: 1024 * 1024 * 1024
       })
 
-      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
+      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
     })
 
     it('Should fail if exceeding daily quota', async function () {
@@ -1185,7 +1185,7 @@ describe('Test users API validators', function () {
         videoQuotaDaily: 42
       })
 
-      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.FORBIDDEN_403)
+      await uploadVideo(server.url, server.accessToken, {}, HttpStatusCode.PAYLOAD_TOO_LARGE_413)
     })
   })
 
index d605469174cc0339690bb9814fdd139858281af8..5faba82c44d9b7148e43234f1b24076b375fd103 100644 (file)
@@ -348,12 +348,26 @@ describe('Test videos API validator', function () {
       let attaches = {
         videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short_fake.webm')
       }
-      await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
+      await makeUploadRequest({
+        url: server.url,
+        path: path + '/upload',
+        token: server.accessToken,
+        fields,
+        attaches,
+        statusCodeExpected: HttpStatusCode.UNPROCESSABLE_ENTITY_422
+      })
 
       attaches = {
         videofile: join(root(), 'server', 'tests', 'fixtures', 'video_short.mkv')
       }
-      await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
+      await makeUploadRequest({
+        url: server.url,
+        path: path + '/upload',
+        token: server.accessToken,
+        fields,
+        attaches,
+        statusCodeExpected: HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415
+      })
     })
 
     it('Should fail with an incorrect thumbnail file', async function () {
index 3ffa0c093ccb721cab69aa589c380d505acc8129..e300ec34567ec7981dd1aba8c05e0abad4b99b0f 100644 (file)
@@ -25,6 +25,7 @@ import {
   waitJobs,
   waitUntilLiveStarts
 } from '../../../../shared/extra-utils'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -118,7 +119,7 @@ describe('Save replay setting', function () {
 
       await waitJobs(servers)
 
-      await checkVideosExist(liveVideoUUID, false, 200)
+      await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
       await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
     })
 
@@ -130,7 +131,7 @@ describe('Save replay setting', function () {
 
       await waitJobs(servers)
 
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
       await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
     })
 
@@ -142,7 +143,7 @@ describe('Save replay setting', function () {
       await waitJobs(servers)
 
       // Live still exist, but cannot be played anymore
-      await checkVideosExist(liveVideoUUID, false, 200)
+      await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
       await checkVideoState(liveVideoUUID, VideoState.LIVE_ENDED)
 
       // No resolutions saved since we did not save replay
@@ -158,7 +159,7 @@ describe('Save replay setting', function () {
       await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
 
       await waitJobs(servers)
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
 
       await Promise.all([
         addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
@@ -169,8 +170,8 @@ describe('Save replay setting', function () {
 
       await checkVideosExist(liveVideoUUID, false)
 
-      await getVideo(servers[0].url, liveVideoUUID, 401)
-      await getVideo(servers[1].url, liveVideoUUID, 404)
+      await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
+      await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
 
       await checkLiveCleanup(servers[0], liveVideoUUID, [])
     })
@@ -184,7 +185,7 @@ describe('Save replay setting', function () {
       await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
 
       await waitJobs(servers)
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
 
       await Promise.all([
         testFfmpegStreamError(ffmpegCommand, true),
@@ -193,7 +194,7 @@ describe('Save replay setting', function () {
 
       await waitJobs(servers)
 
-      await checkVideosExist(liveVideoUUID, false, 404)
+      await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
       await checkLiveCleanup(servers[0], liveVideoUUID, [])
     })
   })
@@ -207,7 +208,7 @@ describe('Save replay setting', function () {
 
       await waitJobs(servers)
 
-      await checkVideosExist(liveVideoUUID, false, 200)
+      await checkVideosExist(liveVideoUUID, false, HttpStatusCode.OK_200)
       await checkVideoState(liveVideoUUID, VideoState.WAITING_FOR_LIVE)
     })
 
@@ -219,7 +220,7 @@ describe('Save replay setting', function () {
 
       await waitJobs(servers)
 
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
       await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
     })
 
@@ -231,7 +232,7 @@ describe('Save replay setting', function () {
       await waitJobs(servers)
 
       // Live has been transcoded
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
       await checkVideoState(liveVideoUUID, VideoState.PUBLISHED)
     })
 
@@ -261,7 +262,7 @@ describe('Save replay setting', function () {
       await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
 
       await waitJobs(servers)
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
 
       await Promise.all([
         addVideoToBlacklist(servers[0].url, servers[0].accessToken, liveVideoUUID, 'bad live', true),
@@ -272,8 +273,8 @@ describe('Save replay setting', function () {
 
       await checkVideosExist(liveVideoUUID, false)
 
-      await getVideo(servers[0].url, liveVideoUUID, 401)
-      await getVideo(servers[1].url, liveVideoUUID, 404)
+      await getVideo(servers[0].url, liveVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
+      await getVideo(servers[1].url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
 
       await checkLiveCleanup(servers[0], liveVideoUUID, [ 720 ])
     })
@@ -287,7 +288,7 @@ describe('Save replay setting', function () {
       await waitUntilLiveStarts(servers[0].url, servers[0].accessToken, liveVideoUUID)
 
       await waitJobs(servers)
-      await checkVideosExist(liveVideoUUID, true, 200)
+      await checkVideosExist(liveVideoUUID, true, HttpStatusCode.OK_200)
 
       await Promise.all([
         removeVideo(servers[0].url, servers[0].accessToken, liveVideoUUID),
@@ -296,7 +297,7 @@ describe('Save replay setting', function () {
 
       await waitJobs(servers)
 
-      await checkVideosExist(liveVideoUUID, false, 404)
+      await checkVideosExist(liveVideoUUID, false, HttpStatusCode.NOT_FOUND_404)
       await checkLiveCleanup(servers[0], liveVideoUUID, [])
     })
   })
index d784650b5618499fa37032ff6ac526e460c7858d..fdfc6105f34ba9cf695b1e720996644c2ce24313 100644 (file)
@@ -44,6 +44,7 @@ import {
   waitUntilLiveStarts,
   waitUntilLog
 } from '../../../../shared/extra-utils'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -164,8 +165,8 @@ describe('Test live', function () {
         expect(video.privacy.id).to.equal(VideoPrivacy.UNLISTED)
         expect(video.nsfw).to.be.true
 
-        await makeRawRequest(server.url + video.thumbnailPath, 200)
-        await makeRawRequest(server.url + video.previewPath, 200)
+        await makeRawRequest(server.url + video.thumbnailPath, HttpStatusCode.OK_200)
+        await makeRawRequest(server.url + video.previewPath, HttpStatusCode.OK_200)
       }
     })
 
@@ -179,7 +180,7 @@ describe('Test live', function () {
     })
 
     it('Should not be able to update a live of another server', async function () {
-      await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, 403)
+      await updateLive(servers[1].url, servers[1].accessToken, liveVideoUUID, { saveReplay: false }, HttpStatusCode.FORBIDDEN_403)
     })
 
     it('Should update the live', async function () {
@@ -215,8 +216,8 @@ describe('Test live', function () {
 
     it('Should have the live deleted', async function () {
       for (const server of servers) {
-        await getVideo(server.url, liveVideoUUID, 404)
-        await getLive(server.url, server.accessToken, liveVideoUUID, 404)
+        await getVideo(server.url, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
+        await getLive(server.url, server.accessToken, liveVideoUUID, HttpStatusCode.NOT_FOUND_404)
       }
     })
   })
@@ -430,8 +431,8 @@ describe('Test live', function () {
         expect(video.files).to.have.lengthOf(0)
 
         const hlsPlaylist = video.streamingPlaylists.find(s => s.type === VideoStreamingPlaylistType.HLS)
-        await makeRawRequest(hlsPlaylist.playlistUrl, 200)
-        await makeRawRequest(hlsPlaylist.segmentsSha256Url, 200)
+        await makeRawRequest(hlsPlaylist.playlistUrl, HttpStatusCode.OK_200)
+        await makeRawRequest(hlsPlaylist.segmentsSha256Url, HttpStatusCode.OK_200)
 
         expect(hlsPlaylist.files).to.have.lengthOf(resolutions.length)
 
@@ -455,8 +456,8 @@ describe('Test live', function () {
 
           expect(probe.format.bit_rate).to.be.below(bitrateLimits[videoStream.height])
 
-          await makeRawRequest(file.torrentUrl, 200)
-          await makeRawRequest(file.fileUrl, 200)
+          await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
+          await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
         }
       }
     })
index eb51d8909c1f1284327f67173ebd26d0242fdf94..a505b8eded6dff00a963d153f5962b4f47c81690 100644 (file)
@@ -21,6 +21,7 @@ import {
   uploadVideo
 } from '../../../../shared/extra-utils'
 import { ServerConfig } from '../../../../shared/models'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -237,8 +238,8 @@ describe('Test config', function () {
     expect(data.video.file.extensions).to.contain('.webm')
     expect(data.video.file.extensions).to.contain('.ogv')
 
-    await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, 400)
-    await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, 400)
+    await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
+    await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415)
 
     expect(data.contactForm.enabled).to.be.true
   })
@@ -427,8 +428,8 @@ describe('Test config', function () {
     expect(data.video.file.extensions).to.contain('.ogg')
     expect(data.video.file.extensions).to.contain('.flac')
 
-    await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, 200)
-    await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, 200)
+    await uploadVideo(server.url, server.accessToken, { fixture: 'video_short.mkv' }, HttpStatusCode.OK_200)
+    await uploadVideo(server.url, server.accessToken, { fixture: 'sample.ogg' }, HttpStatusCode.OK_200)
   })
 
   it('Should have the configuration updated after a restart', async function () {
index c0965d9d1bd429e3302a4048a4dd489fd471ed9c..9b4af19153e7f2d1d4f6b00cf3214f66540e4189 100644 (file)
@@ -6,6 +6,7 @@ import { cleanupTests, flushAndRunServer, ServerInfo, setAccessTokensToServers,
 import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
 import { sendContactForm } from '../../../../shared/extra-utils/server/contact-form'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -67,7 +68,7 @@ describe('Test contact form', function () {
       body: 'my super message',
       fromName: 'Super toto',
       subject: 'my subject',
-      expectedStatus: 403
+      expectedStatus: HttpStatusCode.FORBIDDEN_403
     })
   })
 
index 53f96a94fa17776150572b2accef06f597fbd348..17d9e902ccc18a25a08c435916fb77eefbd0b28d 100644 (file)
@@ -22,6 +22,7 @@ import {
 } from '../../../../shared/extra-utils'
 import { MockSmtpServer } from '../../../../shared/extra-utils/miscs/email'
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -116,7 +117,7 @@ describe('Test emails', function () {
     })
 
     it('Should not reset the password with an invalid verification string', async function () {
-      await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', 403)
+      await resetPassword(server.url, userId, verificationString + 'b', 'super_password2', HttpStatusCode.FORBIDDEN_403)
     })
 
     it('Should reset the password', async function () {
@@ -124,7 +125,7 @@ describe('Test emails', function () {
     })
 
     it('Should not reset the password with the same verification string', async function () {
-      await resetPassword(server.url, userId, verificationString, 'super_password3', 403)
+      await resetPassword(server.url, userId, verificationString, 'super_password3', HttpStatusCode.FORBIDDEN_403)
     })
 
     it('Should login with this new password', async function () {
@@ -169,7 +170,7 @@ describe('Test emails', function () {
     })
 
     it('Should not reset the password with an invalid verification string', async function () {
-      await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', 403)
+      await resetPassword(server.url, userId2, verificationString2 + 'c', 'newly_created_password', HttpStatusCode.FORBIDDEN_403)
     })
 
     it('Should reset the password', async function () {
@@ -210,7 +211,7 @@ describe('Test emails', function () {
       this.timeout(10000)
 
       const reason = 'my super bad reason'
-      await blockUser(server.url, userId, server.accessToken, 204, reason)
+      await blockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204, reason)
 
       await waitJobs(server)
       expect(emails).to.have.lengthOf(4)
@@ -228,7 +229,7 @@ describe('Test emails', function () {
     it('Should send the notification email when unblocking a user', async function () {
       this.timeout(10000)
 
-      await unblockUser(server.url, userId, server.accessToken, 204)
+      await unblockUser(server.url, userId, server.accessToken, HttpStatusCode.NO_CONTENT_204)
 
       await waitJobs(server)
       expect(emails).to.have.lengthOf(5)
@@ -317,7 +318,7 @@ describe('Test emails', function () {
     })
 
     it('Should not verify the email with an invalid verification string', async function () {
-      await verifyEmail(server.url, userId, verificationString + 'b', false, 403)
+      await verifyEmail(server.url, userId, verificationString + 'b', false, HttpStatusCode.FORBIDDEN_403)
     })
 
     it('Should verify the email', async function () {
index a73440286560505063abc97a5cef58e72aec3c62..0846b04f418d2021a47b02500b243d63c3b6236b 100644 (file)
@@ -17,6 +17,7 @@ import {
 import { unfollow } from '../../../../shared/extra-utils/server/follows'
 import { userLogin } from '../../../../shared/extra-utils/users/login'
 import { createUser } from '../../../../shared/extra-utils/users/users'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -58,11 +59,11 @@ describe('Test follow constraints', function () {
     describe('With an unlogged user', function () {
 
       it('Should get the local video', async function () {
-        await getVideo(servers[0].url, video1UUID, 200)
+        await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
       })
 
       it('Should get the remote video', async function () {
-        await getVideo(servers[0].url, video2UUID, 200)
+        await getVideo(servers[0].url, video2UUID, HttpStatusCode.OK_200)
       })
 
       it('Should list local account videos', async function () {
@@ -98,11 +99,11 @@ describe('Test follow constraints', function () {
 
     describe('With a logged user', function () {
       it('Should get the local video', async function () {
-        await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200)
+        await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
       })
 
       it('Should get the remote video', async function () {
-        await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200)
+        await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
       })
 
       it('Should list local account videos', async function () {
@@ -148,11 +149,11 @@ describe('Test follow constraints', function () {
     describe('With an unlogged user', function () {
 
       it('Should get the local video', async function () {
-        await getVideo(servers[0].url, video1UUID, 200)
+        await getVideo(servers[0].url, video1UUID, HttpStatusCode.OK_200)
       })
 
       it('Should not get the remote video', async function () {
-        await getVideo(servers[0].url, video2UUID, 403)
+        await getVideo(servers[0].url, video2UUID, HttpStatusCode.FORBIDDEN_403)
       })
 
       it('Should list local account videos', async function () {
@@ -188,11 +189,11 @@ describe('Test follow constraints', function () {
 
     describe('With a logged user', function () {
       it('Should get the local video', async function () {
-        await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, 200)
+        await getVideoWithToken(servers[0].url, userAccessToken, video1UUID, HttpStatusCode.OK_200)
       })
 
       it('Should get the remote video', async function () {
-        await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, 200)
+        await getVideoWithToken(servers[0].url, userAccessToken, video2UUID, HttpStatusCode.OK_200)
       })
 
       it('Should list local account videos', async function () {
index 2cf6e15adcd9290fda9bc4cc837841f10b0641ad..043754e706faa49fa1c86633d43de2a0fd6cbfce 100644 (file)
@@ -33,6 +33,7 @@ import {
   getVideoCommentThreads,
   getVideoThreadComments
 } from '../../../../shared/extra-utils/videos/video-comments'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -352,7 +353,7 @@ describe('Test handle downs', function () {
     }
 
     for (const id of videoIdsServer1) {
-      await getVideo(servers[1].url, id, 403)
+      await getVideo(servers[1].url, id, HttpStatusCode.FORBIDDEN_403)
     }
   })
 
index d0450aba0b4496ea4589b8594831777d1014203f..d589f51f3e6ef1b6ccd4013fb32f3cf4666bb724 100644 (file)
@@ -2,6 +2,7 @@ import 'mocha'
 import * as request from 'supertest'
 import { ServerInfo } from '../../../../shared/extra-utils'
 import { cleanupTests, flushAndRunServer } from '../../../../shared/extra-utils/server/servers'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Start and stop server without web client routes', function () {
   let server: ServerInfo
@@ -16,7 +17,7 @@ describe('Start and stop server without web client routes', function () {
     const req = request(server.url)
       .get('/')
 
-    return req.expect(404)
+    return req.expect(HttpStatusCode.NOT_FOUND_404)
   })
 
   after(async function () {
index d0d79c4f616683a361c4684e1448223594dc61b8..17d1ee4a573e47ae0a51417b80746faee8fdaf1c 100644 (file)
@@ -4,6 +4,7 @@ import 'mocha'
 import * as chai from 'chai'
 import { cleanupTests, getVideo, registerUser, uploadVideo, userLogin, viewVideo, wait } from '../../../../shared/extra-utils'
 import { flushAndRunServer, setAccessTokensToServers } from '../../../../shared/extra-utils/index'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -56,8 +57,8 @@ describe('Test application behind a reverse proxy', function () {
   it('Should view a video 2 times with the X-Forwarded-For header set', async function () {
     this.timeout(20000)
 
-    await viewVideo(server.url, videoId, 204, '0.0.0.1,127.0.0.1')
-    await viewVideo(server.url, videoId, 204, '0.0.0.2,127.0.0.1')
+    await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.1,127.0.0.1')
+    await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.2,127.0.0.1')
 
     // Wait the repeatable job
     await wait(8000)
@@ -69,8 +70,8 @@ describe('Test application behind a reverse proxy', function () {
   it('Should view a video only once with the same client IP in the X-Forwarded-For header', async function () {
     this.timeout(20000)
 
-    await viewVideo(server.url, videoId, 204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1')
-    await viewVideo(server.url, videoId, 204, '0.0.0.5,0.0.0.3,127.0.0.1')
+    await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.4,0.0.0.3,::ffff:127.0.0.1')
+    await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.5,0.0.0.3,127.0.0.1')
 
     // Wait the repeatable job
     await wait(8000)
@@ -82,8 +83,8 @@ describe('Test application behind a reverse proxy', function () {
   it('Should view a video two times with a different client IP in the X-Forwarded-For header', async function () {
     this.timeout(20000)
 
-    await viewVideo(server.url, videoId, 204, '0.0.0.8,0.0.0.6,127.0.0.1')
-    await viewVideo(server.url, videoId, 204, '0.0.0.8,0.0.0.7,127.0.0.1')
+    await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.6,127.0.0.1')
+    await viewVideo(server.url, videoId, HttpStatusCode.NO_CONTENT_204, '0.0.0.8,0.0.0.7,127.0.0.1')
 
     // Wait the repeatable job
     await wait(8000)
@@ -96,10 +97,10 @@ describe('Test application behind a reverse proxy', function () {
     const user = { username: 'root', password: 'fail' }
 
     for (let i = 0; i < 19; i++) {
-      await userLogin(server, user, 400)
+      await userLogin(server, user, HttpStatusCode.BAD_REQUEST_400)
     }
 
-    await userLogin(server, user, 429)
+    await userLogin(server, user, HttpStatusCode.TOO_MANY_REQUESTS_429)
   })
 
   it('Should rate limit signup', async function () {
@@ -111,7 +112,7 @@ describe('Test application behind a reverse proxy', function () {
       }
     }
 
-    await registerUser(server.url, 'test42', 'password', 429)
+    await registerUser(server.url, 'test42', 'password', HttpStatusCode.TOO_MANY_REQUESTS_429)
   })
 
   it('Should not rate limit failed signup', async function () {
@@ -120,10 +121,10 @@ describe('Test application behind a reverse proxy', function () {
     await wait(7000)
 
     for (let i = 0; i < 3; i++) {
-      await registerUser(server.url, 'test' + i, 'password', 409)
+      await registerUser(server.url, 'test' + i, 'password', HttpStatusCode.CONFLICT_409)
     }
 
-    await registerUser(server.url, 'test43', 'password', 204)
+    await registerUser(server.url, 'test43', 'password', HttpStatusCode.NO_CONTENT_204)
 
   })
 
@@ -140,7 +141,7 @@ describe('Test application behind a reverse proxy', function () {
       }
     }
 
-    await getVideo(server.url, videoId, 429)
+    await getVideo(server.url, videoId, HttpStatusCode.TOO_MANY_REQUESTS_429)
   })
 
   after(async function () {
index fdd5e33f33f3d9cd89e4260a2659aee8b1bfd8b9..f754df04e104d6861608ddc9ab3d7020497f212e 100644 (file)
@@ -41,6 +41,7 @@ import {
   findCommentId
 } from '../../../../shared/extra-utils/videos/video-comments'
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -999,7 +1000,7 @@ describe('Test multiple servers', function () {
         expect(res.body.downloadEnabled).to.be.false
 
         const text = 'my super forbidden comment'
-        await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, 409)
+        await addVideoCommentThread(server.url, server.accessToken, videoUUID, text, HttpStatusCode.CONFLICT_409)
       }
     })
   })
@@ -1021,7 +1022,7 @@ describe('Test multiple servers', function () {
       const filePath = join(__dirname, '..', '..', 'fixtures', 'video_short.webm')
 
       await req.attach('videofile', filePath)
-               .expect(200)
+               .expect(HttpStatusCode.OK_200)
 
       await waitJobs(servers)
 
index dee6575b92f6f078943333ca0873f36dc175ac34..fad4c8b1fb036c8934a8a32dc6cfebb29e0bd1b7 100644 (file)
@@ -23,6 +23,7 @@ import {
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
 import { User } from '../../../../shared/models/users'
 import { VideoDetails } from '../../../../shared/models/videos'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -140,7 +141,7 @@ describe('Test video change ownership - nominal', function () {
   it('Should not be possible to refuse the change of ownership from first user', async function () {
     this.timeout(10000)
 
-    await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, 403)
+    await refuseChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should be possible to refuse the change of ownership from second user', async function () {
@@ -177,7 +178,7 @@ describe('Test video change ownership - nominal', function () {
     const secondUserInformationResponse = await getMyUserInformation(servers[0].url, secondUserAccessToken)
     const secondUserInformation: User = secondUserInformationResponse.body
     const channelId = secondUserInformation.videoChannels[0].id
-    await acceptChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, channelId, 403)
+    await acceptChangeOwnership(servers[0].url, firstUserAccessToken, lastRequestChangeOwnershipId, channelId, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should be possible to accept the change of ownership from second user', async function () {
@@ -294,7 +295,14 @@ describe('Test video change ownership - quota too small', function () {
     const secondUserInformationResponse = await getMyUserInformation(server.url, secondUserAccessToken)
     const secondUserInformation: User = secondUserInformationResponse.body
     const channelId = secondUserInformation.videoChannels[0].id
-    await acceptChangeOwnership(server.url, secondUserAccessToken, lastRequestChangeOwnershipId, channelId, 403)
+
+    await acceptChangeOwnership(
+      server.url,
+      secondUserAccessToken,
+      lastRequestChangeOwnershipId,
+      channelId,
+      HttpStatusCode.PAYLOAD_TOO_LARGE_413
+    )
   })
 
   after(async function () {
index 3a65cc1d2c73bfaa9db4c6833f2cc5a813775875..f3dbbb1143daa871c33a638a9d31ff3c91ce39a6 100644 (file)
@@ -26,6 +26,7 @@ import {
 import { VideoDetails } from '../../../../shared/models/videos'
 import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type'
 import { DEFAULT_AUDIO_RESOLUTION } from '../../../initializers/constants'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -57,8 +58,8 @@ async function checkHlsPlaylist (servers: ServerInfo[], videoUUID: string, hlsOn
       )
       expect(file.resolution.label).to.equal(resolution + 'p')
 
-      await makeRawRequest(file.torrentUrl, 200)
-      await makeRawRequest(file.fileUrl, 200)
+      await makeRawRequest(file.torrentUrl, HttpStatusCode.OK_200)
+      await makeRawRequest(file.fileUrl, HttpStatusCode.OK_200)
 
       const torrent = await webtorrentAdd(file.magnetUri, true)
       expect(torrent.files).to.be.an('array')
@@ -144,8 +145,8 @@ describe('Test HLS videos', function () {
       await waitJobs(servers)
 
       for (const server of servers) {
-        await getVideo(server.url, videoUUID, 404)
-        await getVideo(server.url, videoAudioUUID, 404)
+        await getVideo(server.url, videoUUID, HttpStatusCode.NOT_FOUND_404)
+        await getVideo(server.url, videoAudioUUID, HttpStatusCode.NOT_FOUND_404)
       }
     })
 
index 7d12159900e710f2b41b269b4eb1132485bfbf5e..0a96ea9a0047f7a722a8a1f7800973889a62618b 100644 (file)
@@ -61,6 +61,7 @@ import {
   removeServerFromAccountBlocklist,
   removeServerFromServerBlocklist
 } from '../../../../shared/extra-utils/users/blocklist'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -1091,7 +1092,7 @@ describe('Test video playlists', function () {
       await waitJobs(servers)
 
       for (const server of servers) {
-        await getVideoPlaylist(server.url, videoPlaylistIds.uuid, 200)
+        await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
       }
 
       const playlistAttrs = { privacy: VideoPlaylistPrivacy.PRIVATE }
@@ -1100,11 +1101,11 @@ describe('Test video playlists', function () {
       await waitJobs(servers)
 
       for (const server of [ servers[1], servers[2] ]) {
-        await getVideoPlaylist(server.url, videoPlaylistIds.uuid, 404)
+        await getVideoPlaylist(server.url, videoPlaylistIds.uuid, HttpStatusCode.NOT_FOUND_404)
       }
-      await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, 401)
+      await getVideoPlaylist(servers[0].url, videoPlaylistIds.uuid, HttpStatusCode.UNAUTHORIZED_401)
 
-      await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, 200)
+      await getVideoPlaylistWithToken(servers[0].url, servers[0].accessToken, videoPlaylistIds.uuid, HttpStatusCode.OK_200)
     })
   })
 
@@ -1118,7 +1119,7 @@ describe('Test video playlists', function () {
       await waitJobs(servers)
 
       for (const server of servers) {
-        await getVideoPlaylist(server.url, playlistServer1UUID, 404)
+        await getVideoPlaylist(server.url, playlistServer1UUID, HttpStatusCode.NOT_FOUND_404)
       }
     })
 
@@ -1178,7 +1179,7 @@ describe('Test video playlists', function () {
       expect(res3.body.displayName).to.equal('channel playlist')
       expect(res3.body.privacy.id).to.equal(VideoPlaylistPrivacy.PRIVATE)
 
-      await getVideoPlaylist(servers[1].url, videoPlaylistUUID, 404)
+      await getVideoPlaylist(servers[1].url, videoPlaylistUUID, HttpStatusCode.NOT_FOUND_404)
     })
 
     it('Should delete an account and delete its playlists', async function () {
index 38e93bbe631361d23c9a05f55e6e7636feee6672..f25d75af4c1be8b99eb18195d433786a8007c89f 100644 (file)
@@ -18,6 +18,7 @@ import { createUser } from '../../../../shared/extra-utils/users/users'
 import { getMyVideos, getVideo, getVideoWithToken, updateVideo } from '../../../../shared/extra-utils/videos/videos'
 import { waitJobs } from '../../../../shared/extra-utils/server/jobs'
 import { Video } from '@shared/models'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -110,8 +111,8 @@ describe('Test video privacy', function () {
   })
 
   it('Should not be able to watch the private/internal video with non authenticated user', async function () {
-    await getVideo(servers[0].url, privateVideoUUID, 401)
-    await getVideo(servers[0].url, internalVideoUUID, 401)
+    await getVideo(servers[0].url, privateVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
+    await getVideo(servers[0].url, internalVideoUUID, HttpStatusCode.UNAUTHORIZED_401)
   })
 
   it('Should not be able to watch the private video with another user', async function () {
@@ -124,15 +125,15 @@ describe('Test video privacy', function () {
     await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
 
     anotherUserToken = await userLogin(servers[0], user)
-    await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, 403)
+    await getVideoWithToken(servers[0].url, anotherUserToken, privateVideoUUID, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should be able to watch the internal video with another user', async function () {
-    await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, 200)
+    await getVideoWithToken(servers[0].url, anotherUserToken, internalVideoUUID, HttpStatusCode.OK_200)
   })
 
   it('Should be able to watch the private video with the correct user', async function () {
-    await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, 200)
+    await getVideoWithToken(servers[0].url, servers[0].accessToken, privateVideoUUID, HttpStatusCode.OK_200)
   })
 
   it('Should upload an unlisted video on server 2', async function () {
@@ -202,7 +203,7 @@ describe('Test video privacy', function () {
   })
 
   it('Should not be able to get non-federated unlisted video from federated server', async function () {
-    await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, 404)
+    await getVideo(servers[1].url, nonFederatedUnlistedVideoUUID, HttpStatusCode.NOT_FOUND_404)
   })
 
   it('Should update the private and internal videos to public on server 1', async function () {
index 6f90e9a57b9a829fd44fdd094c3e1035bd0d0a05..661d603cb9a369cc2765d44d597669bce1ecd553 100644 (file)
@@ -20,6 +20,7 @@ import {
 } from '../../../../shared/extra-utils'
 import { Video, VideoDetails } from '../../../../shared/models/videos'
 import { listMyVideosHistory, removeMyVideosHistory, userWatchVideo } from '../../../../shared/extra-utils/videos/video-history'
+import { HttpStatusCode } from '../../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -171,7 +172,7 @@ describe('Test videos history', function () {
       videosHistoryEnabled: false
     })
 
-    await userWatchVideo(server.url, server.accessToken, video2UUID, 8, 409)
+    await userWatchVideo(server.url, server.accessToken, video2UUID, 8, HttpStatusCode.CONFLICT_409)
   })
 
   it('Should re-enable videos history', async function () {
index 6abb6738f6dbb6e9e2024f17d9b241eb215e89fe..a84463b331fbd05ef5b83431b4c93427b8e6c3f7 100644 (file)
@@ -10,6 +10,7 @@ import {
   ServerInfo,
   setAccessTokensToServers
 } from '../../../shared/extra-utils'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 describe('Test reset password scripts', function () {
   let server: ServerInfo
@@ -28,7 +29,7 @@ describe('Test reset password scripts', function () {
     const env = getEnvCli(server)
     await execCLI(`echo coucou | ${env} npm run reset-password -- -u user_1`)
 
-    await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, 200)
+    await login(server.url, server.client, { username: 'user_1', password: 'coucou' }, HttpStatusCode.OK_200)
   })
 
   after(async function () {
index 92a468192f85ea7a68f771f7a59d1566870e13a3..f1055ea4492ae40265df1893eb459c47f354ba9f 100644 (file)
@@ -31,6 +31,7 @@ import {
 import { waitJobs } from '../../../shared/extra-utils/server/jobs'
 import { addVideoCommentThread } from '../../../shared/extra-utils/videos/video-comments'
 import { User } from '../../../shared/models/users'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 chai.use(require('chai-xml'))
 chai.use(require('chai-json-schema'))
@@ -330,11 +331,16 @@ describe('Test syndication feeds', () => {
     })
 
     it('Should fail with an invalid token', async function () {
-      await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, 403)
+      await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: 'toto' }, HttpStatusCode.FORBIDDEN_403)
     })
 
     it('Should fail with a token of another user', async function () {
-      await getJSONfeed(servers[0].url, 'subscriptions', { accountId: feeduserAccountId, token: userFeedToken }, 403)
+      await getJSONfeed(
+        servers[0].url,
+        'subscriptions',
+        { accountId: feeduserAccountId, token: userFeedToken },
+        HttpStatusCode.FORBIDDEN_403
+      )
     })
 
     it('Should list no videos for a user with videos but no subscriptions', async function () {
@@ -382,7 +388,12 @@ describe('Test syndication feeds', () => {
     it('Should renew the token, and so have an invalid old token', async function () {
       await renewUserScopedTokens(servers[0].url, userAccessToken)
 
-      await getJSONfeed(servers[0].url, 'subscriptions', { accountId: userAccountId, token: userFeedToken, version: 3 }, 403)
+      await getJSONfeed(
+        servers[0].url,
+        'subscriptions',
+        { accountId: userAccountId, token: userFeedToken, version: 3 },
+        HttpStatusCode.FORBIDDEN_403
+      )
     })
 
     it('Should succeed with the new token', async function () {
index 2441940c313216de396a6cc0d9613392c8d56863..cdde6cd30aeda589eeec4c00c4a11925311750c7 100644 (file)
@@ -31,6 +31,7 @@ import { cleanupTests, flushAndRunMultipleServers, ServerInfo } from '../../../s
 import { getGoodVideoUrl, getMyVideoImports, importVideo } from '../../../shared/extra-utils/videos/video-imports'
 import { VideoDetails, VideoImport, VideoImportState, VideoPrivacy } from '../../../shared/models/videos'
 import { VideoCommentThreadTree } from '../../../shared/models/videos/video-comment.model'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -127,7 +128,7 @@ describe('Test plugin filter hooks', function () {
   })
 
   it('Should run filter:api.video.upload.accept.result', async function () {
-    await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, 403)
+    await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'video with bad word' }, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should run filter:api.live-video.create.accept.result', async function () {
@@ -137,7 +138,7 @@ describe('Test plugin filter hooks', function () {
       channelId: servers[0].videoChannel.id
     }
 
-    await createLive(servers[0].url, servers[0].accessToken, attributes, 403)
+    await createLive(servers[0].url, servers[0].accessToken, attributes, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should run filter:api.video.pre-import-url.accept.result', async function () {
@@ -147,7 +148,7 @@ describe('Test plugin filter hooks', function () {
       channelId: servers[0].videoChannel.id,
       targetUrl: getGoodVideoUrl() + 'bad'
     }
-    await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, 403)
+    await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should run filter:api.video.pre-import-torrent.accept.result', async function () {
@@ -157,7 +158,7 @@ describe('Test plugin filter hooks', function () {
       channelId: servers[0].videoChannel.id,
       torrentfile: 'video-720p.torrent' as any
     }
-    await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, 403)
+    await importVideo(servers[0].url, servers[0].accessToken, baseAttributes, HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should run filter:api.video.post-import-url.accept.result', async function () {
@@ -219,15 +220,22 @@ describe('Test plugin filter hooks', function () {
   })
 
   it('Should run filter:api.video-thread.create.accept.result', async function () {
-    await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', 403)
+    await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'comment with bad word', HttpStatusCode.FORBIDDEN_403)
   })
 
   it('Should run filter:api.video-comment-reply.create.accept.result', async function () {
     const res = await addVideoCommentThread(servers[0].url, servers[0].accessToken, videoUUID, 'thread')
     threadId = res.body.comment.id
 
-    await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with bad word', 403)
-    await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', 200)
+    await addVideoCommentReply(
+      servers[0].url,
+      servers[0].accessToken,
+      videoUUID,
+      threadId,
+      'comment with bad word',
+      HttpStatusCode.FORBIDDEN_403
+    )
+    await addVideoCommentReply(servers[0].url, servers[0].accessToken, videoUUID, threadId, 'comment with good word', HttpStatusCode.OK_200)
   })
 
   it('Should run filter:api.video-threads.list.params', async function () {
@@ -326,7 +334,7 @@ describe('Test plugin filter hooks', function () {
     })
 
     it('Should not allow a signup', async function () {
-      const res = await registerUser(servers[0].url, 'jma', 'password', 403)
+      const res = await registerUser(servers[0].url, 'jma', 'password', HttpStatusCode.FORBIDDEN_403)
 
       expect(res.body.error).to.equal('No jma')
     })
index fec9196e25704caa8c2cfeaf07ce580c50a62bf8..5ee41fee14d8c4164478e3711cb619cc54fbaab5 100644 (file)
@@ -16,6 +16,7 @@ import {
   uploadVideo
 } from '../../../shared/extra-utils'
 import { VideoDetails, VideoPlaylistPrivacy } from '../../../shared/models/videos'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 const expect = chai.expect
 
@@ -89,12 +90,17 @@ describe('Test plugin altering video constants', function () {
 
   it('Should not be able to create a video with this privacy', async function () {
     const attrs = { name: 'video', privacy: 2 }
-    await uploadVideo(server.url, server.accessToken, attrs, 400)
+    await uploadVideo(server.url, server.accessToken, attrs, HttpStatusCode.BAD_REQUEST_400)
   })
 
   it('Should not be able to create a video with this privacy', async function () {
     const attrs = { displayName: 'video playlist', privacy: VideoPlaylistPrivacy.PRIVATE }
-    await createVideoPlaylist({ url: server.url, token: server.accessToken, playlistAttrs: attrs, expectedStatus: 400 })
+    await createVideoPlaylist({
+      url: server.url,
+      token: server.accessToken,
+      playlistAttrs: attrs,
+      expectedStatus: HttpStatusCode.BAD_REQUEST_400
+    })
   })
 
   it('Should be able to upload a video with these values', async function () {
index 1ab58a438f2cfc55145a811cc9d950b40023983c..fe482daf4857dc68e9c8d4e31d38d416aca13794 100644 (file)
@@ -7,6 +7,7 @@ import * as program from 'commander'
 import { getAdminTokenOrDie, getServerCredentials } from './cli'
 import { VideoRedundanciesTarget, VideoRedundancy } from '@shared/models'
 import { addVideoRedundancy, listVideoRedundancies, removeVideoRedundancy } from '@shared/extra-utils/server/redundancy'
+import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 import validator from 'validator'
 import * as CliTable3 from 'cli-table3'
 import { URL } from 'url'
@@ -124,9 +125,9 @@ async function addRedundancyCLI (options: { videoId: number }) {
 
     process.exit(0)
   } catch (err) {
-    if (err.message.includes(409)) {
+    if (err.message.includes(HttpStatusCode.CONFLICT_409)) {
       console.error('This video is already duplicated by your instance.')
-    } else if (err.message.includes(404)) {
+    } else if (err.message.includes(HttpStatusCode.NOT_FOUND_404)) {
       console.error('This video id does not exist.')
     } else {
       console.error(err)
index 8c8b87ba0e9efe82c61f68ed38c763c8520e1093..9ac8a6c831a44aef2218c702fa2073fdc0832f32 100644 (file)
@@ -1,6 +1,8 @@
 /**
  * Hypertext Transfer Protocol (HTTP) response status codes.
  * @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes}
+ *
+ * WebDAV and other codes useless with regards to PeerTube are not listed.
  */
 export enum HttpStatusCode {
 
@@ -47,15 +49,6 @@ export enum HttpStatusCode {
    */
   ACCEPTED_202 = 202,
 
-  /**
-   * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.4
-   *
-   * SINCE HTTP/1.1
-   * The server is a transforming proxy that received a 200 OK from its origin,
-   * but is returning a modified version of the origin's response.
-   */
-  NON_AUTHORITATIVE_INFORMATION_203 = 203,
-
   /**
    * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.3.5
    *
@@ -77,18 +70,6 @@ export enum HttpStatusCode {
    */
   PARTIAL_CONTENT_206 = 206,
 
-  /**
-   * The message body that follows is an XML message and can contain a number of separate response codes,
-   * depending on how many sub-requests were made.
-   */
-  MULTI_STATUS_207 = 207,
-
-  /**
-   * The server has fulfilled a request for the resource,
-   * and the response is a representation of the result of one or more instance-manipulations applied to the current instance.
-   */
-  IM_USED_226 = 226,
-
   /**
    * Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation).
    * For example, this code could be used to present multiple video format options,
@@ -128,20 +109,6 @@ export enum HttpStatusCode {
    */
   NOT_MODIFIED_304 = 304,
 
-  /**
-   * @deprecated
-   * SINCE HTTP/1.1
-   * The requested resource is available only through a proxy, the address for which is provided in the response.
-   * Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status
-   * code, primarily for security reasons.
-   */
-  USE_PROXY_305 = 305,
-
-  /**
-   * No longer used. Originally meant "Subsequent requests should use the specified proxy."
-   */
-  SWITCH_PROXY_306 = 306,
-
   /**
    * SINCE HTTP/1.1
    * In this case, the request should be repeated with another URI; however, future requests should still use the original URI.
@@ -175,6 +142,8 @@ export enum HttpStatusCode {
   UNAUTHORIZED_401 = 401,
 
   /**
+   * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.2
+   *
    * Reserved for future use. The original intention was that this code might be used as part of some form of digital
    * cash or micro payment scheme, but that has not happened, and this code is not usually used.
    * Google Developers API uses this status if a particular developer has exceeded the daily limit on requests.
@@ -210,11 +179,6 @@ export enum HttpStatusCode {
    */
   NOT_ACCEPTABLE_406 = 406,
 
-  /**
-   * The client must first authenticate itself with the proxy.
-   */
-  PROXY_AUTHENTICATION_REQUIRED_407 = 407,
-
   /**
    * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.7
    *
@@ -222,10 +186,14 @@ export enum HttpStatusCode {
    * It means that the server would like to shut down this unused connection. This response is used much more since
    * some browsers, like Chrome, Firefox 27+, or IE9, use HTTP pre-connection mechanisms to speed up surfing. Also
    * note that some servers merely shut down the connection without sending this message.
+   *
+   * @
    */
   REQUEST_TIMEOUT_408 = 408,
 
   /**
+   * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.5.8
+   *
    * Indicates that the request could not be processed because of conflict in the request,
    * such as an edit conflict between multiple simultaneous updates.
    */
@@ -284,52 +252,39 @@ export enum HttpStatusCode {
   RANGE_NOT_SATISFIABLE_416 = 416,
 
   /**
-   * The server cannot meet the requirements of the Expect request-header field.
+   * The server cannot meet the requirements of the `Expect` request-header field.
    */
   EXPECTATION_FAILED_417 = 417,
 
   /**
+   * Official Documentation @ https://tools.ietf.org/html/rfc2324
+   *
    * This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol,
    * and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by
    * teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including PeerTube instances ;-).
    */
   I_AM_A_TEAPOT_418 = 418,
 
-  /**
-   * The request was directed at a server that is not able to produce a response (for example because a connection reuse).
-   */
-  MISDIRECTED_REQUEST_421 = 421,
-
   /**
    * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.3
    *
    * The request was well-formed but was unable to be followed due to semantic errors.
+   *
+   * @see HttpStatusCode.UNSUPPORTED_MEDIA_TYPE_415 if the `Content-Type` was not supported.
+   * @see HttpStatusCode.BAD_REQUEST_400 if the request was not parsable (broken JSON, XML)
    */
   UNPROCESSABLE_ENTITY_422 = 422,
 
   /**
-   * The resource that is being accessed is locked.
+   * Official Documentation @ https://tools.ietf.org/html/rfc4918#section-11.3
+   *
+   * The resource that is being accessed is locked. WebDAV-specific but used by some HTTP services.
+   *
+   * @deprecated use `If-Match` / `If-None-Match` instead
+   * @see {@link https://evertpot.com/http/423-locked}
    */
   LOCKED_423 = 423,
 
-  /**
-   * The request failed due to failure of a previous request (e.g., a PROPPATCH).
-   */
-  FAILED_DEPENDENCY_424 = 424,
-
-  /**
-   * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field.
-   */
-  UPGRADE_REQUIRED_426 = 426,
-
-  /**
-   * The origin server requires the request to be conditional.
-   * Intended to prevent "the 'lost update' problem, where a client
-   * GETs a resource's state, modifies it, and PUTs it back to the server,
-   * when meanwhile a third party has modified the state on the server, leading to a conflict."
-   */
-  PRECONDITION_REQUIRED_428 = 428,
-
   /**
    * Official Documentation @ https://tools.ietf.org/html/rfc6585#section-4
    *
@@ -359,6 +314,8 @@ export enum HttpStatusCode {
   INTERNAL_SERVER_ERROR_500 = 500,
 
   /**
+   * Official Documentation @ https://tools.ietf.org/html/rfc7231#section-6.6.2
+   *
    * The server either does not recognize the request method, or it lacks the ability to fulfill the request.
    * Usually this implies future availability (e.g., a new feature of a web-service API).
    */
@@ -385,11 +342,6 @@ export enum HttpStatusCode {
    */
   HTTP_VERSION_NOT_SUPPORTED_505 = 505,
 
-  /**
-   * Transparent content negotiation for the request results in a circular reference.
-   */
-  VARIANT_ALSO_NEGOTIATES_506 = 506,
-
   /**
    * Official Documentation @ https://tools.ietf.org/html/rfc2518#section-10.6
    *
@@ -397,23 +349,8 @@ export enum HttpStatusCode {
    * server is unable to store the representation needed to successfully complete the request. This condition is
    * considered to be temporary. If the request which received this status code was the result of a user action,
    * the request MUST NOT be repeated until it is requested by a separate user action.
+   *
+   * @see HttpStatusCode.PAYLOAD_TOO_LARGE_413 for quota errors
    */
   INSUFFICIENT_STORAGE_507 = 507,
-
-  /**
-   * The server detected an infinite loop while processing the request.
-   */
-  LOOP_DETECTED_508 = 508,
-
-  /**
-   * Further extensions to the request are required for the server to fulfill it.
-   */
-  NOT_EXTENDED_510 = 510,
-
-  /**
-   * The client needs to authenticate to gain network access.
-   * Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used
-   * to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot).
-   */
-  NETWORK_AUTHENTICATION_REQUIRED_511 = 511
 }
index eccb198cad17714e99dacbf6e763692b2c734e30..cf967ed7d0c639b47abf4f95a8e81639c6a28cba 100644 (file)
@@ -1,6 +1,7 @@
 import * as request from 'supertest'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
-function makeActivityPubGetRequest (url: string, path: string, expectedStatus = 200) {
+function makeActivityPubGetRequest (url: string, path: string, expectedStatus = HttpStatusCode.OK_200) {
   return request(url)
     .get(path)
     .set('Accept', 'application/activity+json,text/html;q=0.9,\\*/\\*;q=0.8')
index 3aca4ebfdc55b5b1ffd13da039fb1c35a83a0158..b83815a370907c21b34fc5d814bf96a01b769400 100644 (file)
@@ -2,7 +2,13 @@ import { makeDeleteRequest, makeGetRequest, makePostBodyRequest, makePutBodyRequ
 import { VideoRedundanciesTarget } from '@shared/models'
 import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
-function updateRedundancy (url: string, accessToken: string, host: string, redundancyAllowed: boolean, expectedStatus = 204) {
+function updateRedundancy (
+  url: string,
+  accessToken: string,
+  host: string,
+  redundancyAllowed: boolean,
+  expectedStatus = HttpStatusCode.NO_CONTENT_204
+) {
   const path = '/api/v1/server/redundancy/' + host
 
   return makePutBodyRequest({
index 275bb08263e016fd83ea92c19b44166430045176..39e1a2747d0e93ccd39ab549e9b58885b8928bbc 100644 (file)
@@ -2,12 +2,13 @@ import * as request from 'supertest'
 
 import { ServerInfo } from '../server/servers'
 import { getClient } from '../server/clients'
+import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
 type Client = { id: string, secret: string }
 type User = { username: string, password: string }
 type Server = { url: string, client: Client, user: User }
 
-function login (url: string, client: Client, user: User, expectedStatus = 200) {
+function login (url: string, client: Client, user: User, expectedStatus = HttpStatusCode.OK_200) {
   const path = '/api/v1/users/token'
 
   const body = {
@@ -27,7 +28,7 @@ function login (url: string, client: Client, user: User, expectedStatus = 200) {
           .expect(expectedStatus)
 }
 
-function logout (url: string, token: string, expectedStatus = 200) {
+function logout (url: string, token: string, expectedStatus = HttpStatusCode.OK_200) {
   const path = '/api/v1/users/revoke-token'
 
   return request(url)
@@ -38,12 +39,12 @@ function logout (url: string, token: string, expectedStatus = 200) {
 }
 
 async function serverLogin (server: Server) {
-  const res = await login(server.url, server.client, server.user, 200)
+  const res = await login(server.url, server.client, server.user, HttpStatusCode.OK_200)
 
   return res.body.access_token as string
 }
 
-function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus = 200) {
+function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus = HttpStatusCode.OK_200) {
   const path = '/api/v1/users/token'
 
   const body = {
@@ -61,7 +62,7 @@ function refreshToken (server: ServerInfo, refreshToken: string, expectedStatus
     .expect(expectedStatus)
 }
 
-async function userLogin (server: Server, user: User, expectedStatus = 200) {
+async function userLogin (server: Server, user: User, expectedStatus = HttpStatusCode.OK_200) {
   const res = await login(server.url, server.client, user, expectedStatus)
 
   return res.body.access_token as string
@@ -95,7 +96,7 @@ function setAccessTokensToServers (servers: ServerInfo[]) {
   return Promise.all(tasks)
 }
 
-function loginUsingExternalToken (server: Server, username: string, externalAuthToken: string, expectedStatus = 200) {
+function loginUsingExternalToken (server: Server, username: string, externalAuthToken: string, expectedStatus = HttpStatusCode.OK_200) {
   const path = '/api/v1/users/token'
 
   const body = {
index 2d751cf148b1c44bf5381f15bdeb22cdd7693d77..0dd3afb248d205f1a9a2d79ca51e9de3c21844c1 100644 (file)
@@ -1,7 +1,13 @@
 import { makeGetRequest, makePostBodyRequest, makePutBodyRequest } from '../requests/requests'
 import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes'
 
-function userWatchVideo (url: string, token: string, videoId: number | string, currentTime: number, statusCodeExpected = 204) {
+function userWatchVideo (
+  url: string,
+  token: string,
+  videoId: number | string,
+  currentTime: number,
+  statusCodeExpected = HttpStatusCode.NO_CONTENT_204
+) {
   const path = '/api/v1/videos/' + videoId + '/watching'
   const fields = { currentTime }
 
index a4b9d688e69bb0f29685f8aa7ac4ea066518ed7f..a2438d712aaaace0119d1b351be81acf5b2b8ac1 100644 (file)
@@ -155,7 +155,7 @@ function getVideosListWithToken (url: string, token: string, query: { nsfw?: boo
     .set('Authorization', 'Bearer ' + token)
     .query(immutableAssign(query, { sort: 'name' }))
     .set('Accept', 'application/json')
-    .expect(200)
+    .expect(HttpStatusCode.OK_200)
     .expect('Content-Type', /json/)
 }
 
@@ -166,7 +166,7 @@ function getLocalVideos (url: string) {
     .get(path)
     .query({ sort: 'name', filter: 'local' })
     .set('Accept', 'application/json')
-    .expect(200)
+    .expect(HttpStatusCode.OK_200)
     .expect('Content-Type', /json/)
 }
 
index 2d6b4df271aaf9b924cf3c6c5bfa231697332f54..ba420b4a96fc8297ed8827e2824ded1b445025b5 100644 (file)
@@ -1312,20 +1312,24 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoUploadResponse'
+        '400':
+          description: invalid file field, schedule date or parameter
         '403':
-          description: user video quota is exceeded with this video
+          description: video didn't pass upload filter
         '408':
           description: upload has timed out
         '413':
-          description: video file too large
+          description: video file too large, due to quota or max body size limit set by the reverse-proxy
           headers:
             X-File-Maximum-Size:
               schema:
                 type: string
                 format: Nginx size
               description: Maximum file size for the video
+        '415':
+          description: video type unsupported
         '422':
-          description: invalid input file
+          description: video unreadable
       requestBody:
         content:
           multipart/form-data:
@@ -1534,10 +1538,12 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/VideoUploadResponse'
-        '409':
-          description: HTTP or Torrent/magnetURI import not enabled
         '400':
           description: '`magnetUri` or `targetUrl` or a torrent file missing'
+        '403':
+          description: video didn't pass pre-import filter
+        '409':
+          description: HTTP or Torrent/magnetURI import not enabled
 
   /videos/live:
     post:
@@ -3572,7 +3578,7 @@ components:
       name: name
       in: path
       required: true
-      description: The name of the account
+      description: The username or handle of the account
       schema:
         type: string
         example: chocobozzz | chocobozzz@example.org
@@ -5175,7 +5181,7 @@ components:
           properties:
             name:
               type: string
-              description: The name for the default channel
+              description: The username for the default channel
               pattern: '/^[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\\-_.:]+$/'
             displayName:
               type: string