<commit_before>import * as fs from 'fs';
import * as path from 'path';
import * as express from 'express';
import SocketIoServer from './SocketIoServer';
import { PLayList } from '../Model/Api/PlayListInterface';

export interface IError {
    readonly code: number;
    readonly message: string;
    errors?: string;
}

export const responseError = (res: express.Response, reason: IError): express.Response => {
    const error: IError = {
        code: reason.code,
        message: reason.message
    };

    res.status(reason.code);
    res.json(error);
    return res;
}

export const responseServerError = (res: express.Response, err?: string): express.Response => {
    let error: IError = {
        code: 500,
        message: 'Internal Server Error',
    }

    if(typeof err !== 'undefined') {
        error.errors = err;
    }

    res.status(error.code);
    res.json(error);
    return res;
}

export const responseJSON = (res: express.Response, code: number, body?: any): express.Response => {
    res.status(code);
    // non-cache
    res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
    res.header('Expires', '-1');
    res.header('Pragma', 'no-cache');
    res.json(body);

    return res;
}

/**
* socket.io で client へ状態が更新されたことを通知する
*/
export const notifyClient = (): void => {
    SocketIoServer.getInstance().notifyClient();
}

/**
* PLayList を m3u8 としてレスポンスする
*/
export const responsePlayList = (req: express.Request, res: express.Response, list: PLayList): void => {
    res.setHeader('Content-Type', 'application/x-mpegURL; charset="UTF-8"');
    let disposition = /firefox|Firefox/.test(<string>req.headers['user-agent']) ? 'inline' : 'attachment';
    res.setHeader('Content-Disposition', `${ disposition }; filename*=UTF-8''${ list.name };`);
    res.status(200);
    res.write(list.playList);
    res.end();
}

export const responseFile = (req: express.Request, res: express.Response, filePath: string, mime: string, download: boolean = false): void => {
    let stat: fs.Stats;

    stat = fs.statSync(filePath)
    if(stat.isDirectory()) { throw new Error('file path is derectory'); }

    let responseHeaders: {} = {};
    if(download) {
        responseHeaders['Content-Type'] = 'application/octet-stream';
         responseHeaders['Content-disposition'] = "attachment; filename*=utf-8'ja'" + encodeURIComponent(path.basename(filePath)) + ";"
    } else {
        responseHeaders['Content-Type'] = mime;
    }

    let rangeRequest = readRangeHeader(req.headers['range'], stat.size);

    if (rangeRequest == null) {
        responseHeaders['Content-Length'] = stat.size;
        responseHeaders['Accept-Ranges'] = 'bytes';

        sendResponse(200, req, res, responseHeaders, fs.createReadStream(filePath));
        return;
    }

    let start: number = rangeRequest.Start;
    let end: number = rangeRequest.End;

    if (start >= stat.size || end >= stat.size) {
        responseHeaders['Content-Range'] = 'bytes */' + stat.size;
        sendResponse(416, req, res, responseHeaders, null);
        return;
    }
<commit_msg>ファイルレスポンス時に HEAD の場合を考慮するようにした<commit_after>import * as fs from 'fs';
import * as path from 'path';
import * as express from 'express';
import SocketIoServer from './SocketIoServer';
import { PLayList } from '../Model/Api/PlayListInterface';

export interface IError {
    readonly code: number;
    readonly message: string;
    errors?: string;
}

export const responseError = (res: express.Response, reason: IError): express.Response => {
    const error: IError = {
        code: reason.code,
        message: reason.message
    };

    res.status(reason.code);
    res.json(error);
    return res;
}

export const responseServerError = (res: express.Response, err?: string): express.Response => {
    let error: IError = {
        code: 500,
        message: 'Internal Server Error',
    }

    if(typeof err !== 'undefined') {
        error.errors = err;
    }

    res.status(error.code);
    res.json(error);
    return res;
}

export const responseJSON = (res: express.Response, code: number, body?: any): express.Response => {
    res.status(code);
    // non-cache
    res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
    res.header('Expires', '-1');
    res.header('Pragma', 'no-cache');
    res.json(body);

    return res;
}

/**
* socket.io で client へ状態が更新されたことを通知する
*/
export const notifyClient = (): void => {
    SocketIoServer.getInstance().notifyClient();
}

/**
* PLayList を m3u8 としてレスポンスする
*/
export const responsePlayList = (req: express.Request, res: express.Response, list: PLayList): void => {
    res.setHeader('Content-Type', 'application/x-mpegURL; charset="UTF-8"');
    let disposition = /firefox|Firefox/.test(<string>req.headers['user-agent']) ? 'inline' : 'attachment';
    res.setHeader('Content-Disposition', `${ disposition }; filename*=UTF-8''${ list.name };`);
    res.status(200);
    res.write(list.playList);
    res.end();
}

export const responseFile = (req: express.Request, res: express.Response, filePath: string, mime: string, download: boolean = false): void => {
    let stat: fs.Stats;

    stat = fs.statSync(filePath)
    if(stat.isDirectory()) { throw new Error('file path is derectory'); }

    let responseHeaders: {} = {};
    if(download) {
        responseHeaders['Content-Type'] = 'application/octet-stream';
         responseHeaders['Content-disposition'] = "attachment; filename*=utf-8'ja'" + encodeURIComponent(path.basename(filePath)) + ";"
    } else {
        responseHeaders['Content-Type'] = mime;
    }

    let rangeRequest = readRangeHeader(req.headers['range'], stat.size);

    if (rangeRequest == null) {
        responseHeaders['Content-Length'] = stat.size;
        responseHeaders['Accept-Ranges'] = 'bytes';

        sendResponse(200, req, res, responseHeaders, req.method === 'HEAD' ? null : fs.createReadStream(filePath));
        return;
    }

    let start: number = rangeRequest.Start;
    let end: number = rangeRequest.End;

    if (start >= stat.size || end >= stat.size) {
        responseHeaders['Content-Range'] = 'bytes */' + stat.size;
        sendResponse(416, req, res, responseHeaders, null);
        return;
    }

{'fraction_non_alphanumeric': 0.15542710340398203, 'fraction_numerical': 0.005780346820809248, 'mean_word_length': 3.386619718309859, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4791748', 'n_tokens_mistral': 1981, 'n_tokens_neox': 1922, 'n_words': 443}