Exemplo n.º 1
0
        /// <summary>
        /// HTTP文件请求处理
        /// </summary>
        /// <param name="path">请求路径</param>
        /// <param name="ifModifiedSince">文件修改时间</param>
        /// <param name="response">HTTP响应输出</param>
        /// <param name="isCopyPath">是否复制请求路径</param>
        /// <returns>文件缓存</returns>
        protected unsafe FileCache file(byte[] path, SubArray <byte> ifModifiedSince, ref Http.Response response, bool isCopyPath)
        {
            string cacheFileName = null;

            try
            {
                if (path.Length != 0 && WorkPath.Length + path.Length <= AutoCSer.IO.File.MaxFullNameLength)
                {
                    byte[] contentType = null;
                    bool   isCompress  = true;
                    fixed(byte *pathFixed = path)
                    {
                        byte *pathStart = pathFixed, pathEnd = pathStart + path.Length;

                        if (isFile(pathEnd, ref contentType, ref isCompress) == 0)
                        {
                            if (*pathStart == '/')
                            {
                                ++pathStart;
                            }
                            for (byte *formatStart = pathStart; formatStart != pathEnd; ++formatStart)
                            {
                                if (*formatStart == ':')
                                {
                                    response = Http.Response.Blank;
                                    return(null);
                                }
                            }
                            int          cachePathLength = (int)(pathEnd - pathStart);
                            FileCacheKey cacheKey        = new FileCacheKey(pathIdentity, path, (int)(pathStart - pathFixed), cachePathLength);
                            FileCache    fileCache       = FileCacheQueue.Get(ref cacheKey);
                            if (fileCache == null)
                            {
                                cacheFileName = StringExtension.FastAllocateString(WorkPath.Length + cachePathLength);
                                fixed(char *nameFixed = cacheFileName)
                                {
                                    char *write = nameFixed + WorkPath.Length;
                                    char  directorySeparatorChar = Path.DirectorySeparatorChar;

                                    StringExtension.CopyNotNull(WorkPath, nameFixed);
                                    for (byte *start = pathStart; start != pathEnd; ++start)
                                    {
                                        *write++ = *start == '/' ? directorySeparatorChar : (char)*start;
                                    }
                                }
                                FileInfo file = new FileInfo(cacheFileName);
                                if (file.Exists)
                                {
                                    string fileName = file.FullName;
                                    if (fileName.Length > WorkPath.Length && WorkPath.equalCaseNotNull(fileName, WorkPath.Length))
                                    {
                                        if (fileName.Length <= AutoCSer.IO.File.MaxFullNameLength && file.Length <= FileCacheQueue.MaxFileSize)
                                        {
                                            if (FileCacheQueue.Get(ref cacheKey, out fileCache, isCopyPath) != 0)
                                            {
                                                try
                                                {
                                                    fileCache.LastModified = file.LastWriteTimeUtc.UniversalNewBytes();
                                                    int             extensionNameLength = (int)(pathEnd - getExtensionNameStart(pathEnd));
                                                    SubArray <byte> fileData            = readCacheFile(new SubString {
                                                        String = fileName, Start = fileName.Length - extensionNameLength, Length = extensionNameLength
                                                    });
                                                    FileCacheQueue.Set(ref cacheKey, fileCache, fileCache.Set(ref fileData, contentType, cacheControl, isCompress));
                                                    if (ifModifiedSince.Length == fileCache.LastModified.Length)
                                                    {
                                                        fixed(byte *ifModifiedSinceFixed = ifModifiedSince.Array)
                                                        {
                                                            if (Memory.EqualNotNull(fileCache.LastModified, ifModifiedSinceFixed + ifModifiedSince.Start, ifModifiedSince.Length))
                                                            {
                                                                response = Http.Response.NotChanged304;
                                                                return(null);
                                                            }
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    if (fileCache.IsData == 0)
                                                    {
                                                        fileCache.PulseAll();
                                                        fileCache = null;
                                                        FileCacheQueue.RemoveOnly(ref cacheKey);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if (ifModifiedSince.Length == Date.ToByteLength && Date.UniversalByteEquals(file.LastWriteTimeUtc, ifModifiedSince) == 0)
                                            {
                                                response = Http.Response.NotChanged304;
                                                return(null);
                                            }
                                            response = Http.Response.Get();
                                            //response.State = Http.ResponseState.Ok200;
                                            response.SetBodyFile(file);
                                            response.CacheControl = cacheControl;
                                            response.ContentType  = contentType;
                                            response.SetLastModified(file.LastWriteTimeUtc.UniversalNewBytes());
                                            return(null);
                                        }
                                    }
                                }
                            }
                            return(fileCache);
                        }
                    }
                }
            }
            catch (Exception error)
            {
                RegisterServer.TcpServer.Log.Add(AutoCSer.Log.LogType.Error, error, cacheFileName);
            }
            return(null);
        }
Exemplo n.º 2
0
        /// <summary>
        /// HTTP文件请求处理
        /// </summary>
        /// <param name="header">请求头部</param>
        /// <param name="response">HTTP响应输出</param>
        /// <returns>文件缓存</returns>
        protected unsafe FileCache file(Http.Header header, ref Http.Response response)
        {
            SubArray <byte> path          = header.Path;
            string          cacheFileName = null;

            try
            {
                if (path.Length != 0 && WorkPath.Length + path.Length <= AutoCSer.IO.File.MaxFullNameLength)
                {
                    byte[] contentType = null;
                    bool   isCompress  = true;
                    fixed(byte *pathFixed = path.GetFixedBuffer())
                    {
                        byte *pathStart = pathFixed + path.Start, pathEnd = pathStart + path.Length;

                        if (isFile(pathEnd, ref contentType, ref isCompress) == 0)
                        {
                            if (*pathStart == '/')
                            {
                                ++pathStart;
                            }
                            for (byte *formatStart = pathStart; formatStart != pathEnd; ++formatStart)
                            {
                                if (*formatStart == ':')
                                {
                                    response = Http.Response.Blank;
                                    return(null);
                                }
#if !MONO
                                if ((uint)(*formatStart - 'A') < 26)
                                {
                                    *formatStart |= 0x20;
                                }
#endif
                            }
                            int          cachePathLength = (int)(pathEnd - pathStart);
                            FileCacheKey cacheKey        = new FileCacheKey(pathIdentity, path.Array, (int)(pathStart - pathFixed), cachePathLength);
                            FileCache    fileCache       = FileCacheQueue.Get(ref cacheKey);
                            if (fileCache == null)
                            {
                                cacheFileName = StringExtension.FastAllocateString(WorkPath.Length + cachePathLength);
                                fixed(char *nameFixed = cacheFileName)
                                {
                                    char *write = nameFixed + WorkPath.Length;
                                    char  directorySeparatorChar = Path.DirectorySeparatorChar;

                                    StringExtension.CopyNotNull(WorkPath, nameFixed);
                                    for (byte *start = pathStart; start != pathEnd; ++start)
                                    {
                                        *write++ = *start == '/' ? directorySeparatorChar : (char)*start;
                                    }
                                }
                                FileInfo file = new FileInfo(cacheFileName);
                                bool     isFileExists = file.Exists, isCopyPath = true;
                                if (!isFileExists && cacheFileName.IndexOf('%') >= WorkPath.Length)
                                {
                                    cacheKey.CopyPath();
                                    isCopyPath = false;
                                    string newPath = AutoCSer.Net.Http.Header.UnescapeUtf8(pathStart, cachePathLength, path.Array, (int)(pathStart - pathFixed));
                                    if (Path.DirectorySeparatorChar != '/')
                                    {
                                        newPath.replaceNotNull('/', Path.DirectorySeparatorChar);
                                    }
                                    FileInfo newFile = new FileInfo(WorkPath + newPath);
                                    if (newFile.Exists)
                                    {
                                        file         = newFile;
                                        isFileExists = true;
                                    }
                                }
                                if (isFileExists)
                                {
                                    string fileName = file.FullName;
                                    if (fileName.Length > WorkPath.Length && WorkPath.equalCaseNotNull(fileName, WorkPath.Length))
                                    {
                                        if (fileName.Length <= AutoCSer.IO.File.MaxFullNameLength && file.Length <= FileCacheQueue.MaxFileSize)
                                        {
                                            if (FileCacheQueue.Get(ref cacheKey, out fileCache, isCopyPath) != 0)
                                            {
                                                try
                                                {
                                                    fileCache.LastModified = file.LastWriteTimeUtc.UniversalNewBytes();
                                                    int             extensionNameLength = (int)(pathEnd - getExtensionNameStart(pathEnd));
                                                    SubArray <byte> fileData            = readCacheFile(new SubString {
                                                        String = fileName, Start = fileName.Length - extensionNameLength, Length = extensionNameLength
                                                    });
                                                    FileCacheQueue.Set(ref cacheKey, fileCache, fileCache.Set(ref fileData, contentType, cacheControl, isCompress));
                                                    if ((header.Flag & Http.HeaderFlag.IsSetIfModifiedSince) != 0 && header.IfModifiedSinceIndex.Length == fileCache.LastModified.Length)
                                                    {
                                                        if (AutoCSer.Memory.Common.EqualNotNull(fileCache.LastModified, pathFixed + header.Buffer.StartIndex + header.IfModifiedSinceIndex.StartIndex, header.IfModifiedSinceIndex.Length))
                                                        {
                                                            response = Http.Response.NotChanged304;
                                                            return(null);
                                                        }
                                                    }
                                                }
                                                finally
                                                {
                                                    if (fileCache.IsData == 0)
                                                    {
                                                        fileCache.PulseAll();
                                                        fileCache = null;
                                                        FileCacheQueue.RemoveOnly(ref cacheKey);
                                                    }
                                                }
                                            }
                                        }
                                        else
                                        {
                                            if ((header.Flag & Http.HeaderFlag.IsSetIfModifiedSince) != 0 && header.IfModifiedSinceIndex.Length == Date.ToByteLength && Date.UniversalByteEquals(file.LastWriteTimeUtc, header.IfModifiedSince) == 0)
                                            {
                                                response = Http.Response.NotChanged304;
                                                return(null);
                                            }
                                            response = Http.Response.Get();
                                            //response.State = Http.ResponseState.Ok200;
                                            response.SetBodyFile(file);
                                            response.CacheControl = cacheControl;
                                            response.ContentType  = contentType;
                                            response.SetLastModified(file.LastWriteTimeUtc.UniversalNewBytes());
                                            return(null);
                                        }
                                    }
                                }
                            }
                            return(fileCache);
                        }
                    }
                }
            }
            catch (Exception error)
            {
                RegisterServer.TcpServer.Log.Exception(error, cacheFileName, LogLevel.Exception | LogLevel.AutoCSer);
            }
            return(null);
        }