@@ -173,7 +173,7 @@ func (f *FileDao) FileGetGenerator(c echo.Context, repoType, orgRepo, commit, fi
173173 }
174174 authorization := c .Request ().Header .Get ("Authorization" )
175175 // _file_realtime_stream
176- pathsInfos , err := f .GetPathsInfo (repoType , orgRepo , commit , authorization , [] string { fileName } )
176+ pathInfo , err := f .GetPathsInfo (hfUri , repoType , orgRepo , commit , authorization , fileName )
177177 if err != nil {
178178 if e , ok := err .(myerr.Error ); ok {
179179 zap .S ().Errorf ("GetPathsInfo code:%d, err:%v" , e .StatusCode (), err )
@@ -182,42 +182,15 @@ func (f *FileDao) FileGetGenerator(c echo.Context, repoType, orgRepo, commit, fi
182182 zap .S ().Errorf ("GetPathsInfo err:%v" , err )
183183 return util .ErrorProxyError (c )
184184 }
185- if len ( pathsInfos ) == 0 {
185+ if pathInfo == nil {
186186 zap .S ().Errorf ("pathsInfos is null. repo:%s, commit:%s, fileName:%s" , orgRepo , commit , fileName )
187187 return util .ErrorEntryNotFound (c )
188188 }
189- if len (pathsInfos ) != 1 {
190- zap .S ().Errorf ("pathsInfos not equal to 1. repo:%s, commit:%s, fileName:%s" , orgRepo , commit , fileName )
191- return util .ErrorProxyTimeout (c )
192- }
193- pathInfo := pathsInfos [0 ]
194189 if pathInfo .Type == "directory" {
195190 zap .S ().Warnf ("repo:%s, commit:%s, fileName:%s is directory" , orgRepo , commit , fileName )
196191 return util .ErrorEntryNotFound (c )
197192 }
198- var startPos , endPos int64
199- if pathInfo .Size > 0 { // There exists a file of size 0
200- var headRange = c .Request ().Header .Get ("Range" )
201- if headRange == "" {
202- headRange = fmt .Sprintf ("bytes=%d-%d" , 0 , pathInfo .Size - 1 )
203- }
204- startPos , endPos = parseRangeParams (headRange , pathInfo .Size )
205- endPos = endPos + 1
206- } else if pathInfo .Size == 0 {
207- zap .S ().Warnf ("file %s size: %d" , fileName , pathInfo .Size )
208- }
209- respHeaders := map [string ]string {}
210- respHeaders ["content-length" ] = util .Itoa (endPos - startPos )
211- if commit != "" {
212- respHeaders [strings .ToLower (consts .HUGGINGFACE_HEADER_X_REPO_COMMIT )] = commit
213- }
214- var etag string
215- if pathInfo .Lfs .Oid != "" {
216- etag = pathInfo .Lfs .Oid
217- } else {
218- etag = pathInfo .Oid
219- }
220- respHeaders ["etag" ] = etag
193+ respHeaders , etag , startPos , endPos := constructRespHeader (c , pathInfo , commit , fileName )
221194 blobsDir := fmt .Sprintf ("%s/files/%s/%s/blobs" , config .SysConfig .Repos (), repoType , orgRepo )
222195 blobsFile := fmt .Sprintf ("%s/%s" , blobsDir , etag )
223196 filesDir := fmt .Sprintf ("%s/files/%s/%s/resolve/%s" , config .SysConfig .Repos (), repoType , orgRepo , commit )
@@ -245,6 +218,46 @@ func (f *FileDao) FileGetGenerator(c echo.Context, repoType, orgRepo, commit, fi
245218 }
246219}
247220
221+ func constructRespHeader (c echo.Context , pathInfo * common.PathsInfo , commit , fileName string ) (map [string ]string , string , int64 , int64 ) {
222+ var startPos , endPos int64
223+ if pathInfo .Size > 0 { // There exists a file of size 0
224+ var headRange = c .Request ().Header .Get ("Range" )
225+ if headRange == "" {
226+ headRange = fmt .Sprintf ("bytes=%d-%d" , 0 , pathInfo .Size - 1 )
227+ }
228+ startPos , endPos = parseRangeParams (headRange , pathInfo .Size )
229+ endPos = endPos + 1
230+ } else if pathInfo .Size == 0 {
231+ zap .S ().Warnf ("file %s size: %d" , fileName , pathInfo .Size )
232+ }
233+ respHeaders := map [string ]string {}
234+ respHeaders [consts .HUGGINGFACE_HEADER_CONTENT_LENGTH ] = util .Itoa (endPos - startPos )
235+ if commit != "" {
236+ respHeaders [strings .ToLower (consts .HUGGINGFACE_HEADER_X_REPO_COMMIT )] = commit
237+ }
238+ var etag string
239+ if pathInfo .Lfs .Oid != "" {
240+ etag = pathInfo .Lfs .Oid
241+ } else {
242+ etag = pathInfo .Oid
243+ }
244+ respHeaders [consts .HUGGINGFACE_HEADER_X_LINKED_ETAG ] = etag
245+ respHeaders [consts .HUGGINGFACE_HEADER_X_LINKED_SIZE ] = util .Itoa (pathInfo .Size )
246+ if pathInfo .Location != "" {
247+ // clientHost := c.Request().Host
248+ // clientScheme := "http"
249+ // if c.Request().TLS != nil {
250+ // clientScheme = "https"
251+ // }
252+ // hfEndPoint := fmt.Sprintf("%s://%s", clientScheme, clientHost)
253+ // loc := strings.ReplaceAll(pathInfo.Location, config.SysConfig.GetXetURLBase(), hfEndPoint)
254+ respHeaders [consts .HUGGINGFACE_LOCATION ] = pathInfo .Location
255+ respHeaders [consts .HUGGINGFACE_HEADER_X_XET_HASH ] = pathInfo .XXetHash
256+ respHeaders [consts .HUGGINGFACE_Link ] = pathInfo .Link
257+ }
258+ return respHeaders , etag , startPos , endPos
259+ }
260+
248261func GetAnalysisFilePosition (dingFile * downloader.DingCache , startPos , endPos int64 ) int64 {
249262 _ , offset := analysisFilePosition (dingFile , startPos , endPos )
250263 return offset
@@ -293,88 +306,90 @@ func (f *FileDao) ConstructBlobsAndFileFile(blobsFile, filesPath string) (err er
293306 return
294307}
295308
296- func (f * FileDao ) GetPathsInfo (repoType , orgRepo , commit , authorization string , pathFileNames []string ) ([]common.PathsInfo , error ) {
297- ret := make ([]common.PathsInfo , 0 )
298- remoteReqFilePathMap := make (map [string ]string )
299- if len (pathFileNames ) == 0 {
300- return ret , nil
309+ func (f * FileDao ) GetPathsInfo (hfUri , repoType , orgRepo , commit , authorization string , pathFileName string ) (* common.PathsInfo , error ) {
310+ var pathInfo * common.PathsInfo
311+ if pathFileName == "" {
312+ return nil , fmt .Errorf ("pathFileName is null, %s/%s" , orgRepo , commit )
301313 }
314+ apiPathInfoPath := fmt .Sprintf ("%s/api/%s/%s/paths-info/%s/%s/paths-info_post.json" , config .SysConfig .Repos (), repoType , orgRepo , commit , pathFileName )
302315 // 对每个用户检测是否有权限,在线、离线都检测,都需要携带token。
303316 filePathInfoKey := GetFilePathInfoKey (repoType , orgRepo , authorization )
304317 _ , granted := f .baseData .Cache .Get (filePathInfoKey )
305- for _ , pathFileName := range pathFileNames {
306- apiPathInfoPath := fmt .Sprintf ("%s/api/%s/%s/paths-info/%s/%s/paths-info_post.json" , config .SysConfig .Repos (), repoType , orgRepo , commit , pathFileName )
307- if ! granted {
308- remoteReqFilePathMap [pathFileName ] = apiPathInfoPath
309- continue
310- }
311- hitCache := util .FileExists (apiPathInfoPath )
312- if hitCache {
313- if cacheContent , err := f .ReadCacheRequest (apiPathInfoPath ); err != nil { // 若存在缓存文件,却读取失败,将会在线请求。
314- zap .S ().Errorf ("ReadCacheRequest err.%v" , err )
315- } else {
316- if cacheContent .Version != consts .VersionSnapshot {
317- // 若是老版本,需要重新请求pathsInfo数据
318+ if granted && f .ExistApiPathFile (apiPathInfoPath ) { // 已授权的用户,才可以从缓存读取,若存在则返回,否则一律在线请求。
319+ if cacheContent , err := f .ReadCacheRequest (apiPathInfoPath ); err != nil { // 若存在缓存文件,却读取失败,将会在线请求。
320+ zap .S ().Warnf ("ReadCacheRequest err, go to online access%v" , err )
321+ } else {
322+ if cacheContent .Version == consts .VersionSnapshot {
323+ pathsInfos := make ([]common.PathsInfo , 0 )
324+ if err = sonic .Unmarshal (cacheContent .OriginContent , & pathsInfos ); err != nil {
325+ zap .S ().Errorf ("pathsInfo Unmarshal err.%v" , err )
318326 } else {
319- pathsInfos := make ([]common. PathsInfo , 0 )
320- if err = sonic . Unmarshal ( cacheContent . OriginContent , & pathsInfos ); err != nil {
321- zap . S (). Errorf ( "pathsInfo Unmarshal err.%v" , err )
322- } else if cacheContent . StatusCode == http . StatusOK {
323- ret = append ( ret , pathsInfos ... )
324- continue
327+ if len ( pathsInfos ) > 0 {
328+ if pathsInfos [ 0 ]. Size > consts . MAX_HTTP_DOWNLOAD_SIZE {
329+ goto requestRemoteFileInfo
330+ } else {
331+ return & pathsInfos [ 0 ], nil
332+ }
325333 }
326334 }
327335 }
328336 }
329- // 若命中缓存读取失败,将执行在线
330- remoteReqFilePathMap [pathFileName ] = apiPathInfoPath
331337 }
332- if len (remoteReqFilePathMap ) > 0 {
333- filePaths := make ([]string , 0 )
334- for k := range remoteReqFilePathMap {
335- filePaths = append (filePaths , k )
336- }
337- response , err := f .requestFilePath (repoType , orgRepo , commit , authorization , filePaths )
338- if err != nil {
339- return nil , err
340- }
338+ goto requestRemoteFileInfo
339+
340+ requestRemoteFileInfo:
341+ pathsInfoUri := fmt .Sprintf ("/api/%s/%s/paths-info/%s" , repoType , orgRepo , commit )
342+ if response , err := f .requestFilePathInfo (pathsInfoUri , authorization , []string {pathFileName }); err != nil {
343+ return nil , err
344+ } else {
341345 if ! granted {
342346 f .baseData .Cache .Set (filePathInfoKey , "" , 24 * time .Hour )
343347 }
344- remoteRespPathsInfos := make ([]common.PathsInfo , 0 )
348+ remoteRespPathsInfos := make ([]* common.PathsInfo , 0 )
345349 err = sonic .Unmarshal (response .Body , & remoteRespPathsInfos )
346350 if err != nil {
347351 return nil , myerr .NewAppendCode (http .StatusInternalServerError , fmt .Sprintf ("%v" , err ))
348352 }
349- for _ , item := range remoteRespPathsInfos {
350- // 对单个文件pathsInfo做存储
351- if apiPath , ok := remoteReqFilePathMap [item .Path ]; ok {
352- if err = util .MakeDirs (apiPath ); err != nil {
353- zap .S ().Errorf ("create %s dir err.%v" , apiPath , err )
354- continue
355- }
356- if item .Type == "file" {
357- b , _ := sonic .Marshal ([]common.PathsInfo {item }) // 转成单个文件的切片
358- if err = f .WriteCacheRequest (apiPath , response .StatusCode , response .ExtractHeaders (response .Headers ), b ); err != nil {
359- zap .S ().Errorf ("WriteCacheRequest err.%s,%v" , apiPath , err )
360- continue
361- }
362- }
353+ if len (remoteRespPathsInfos ) > 0 {
354+ pathInfo = remoteRespPathsInfos [0 ]
355+ } else {
356+ return nil , myerr .NewAppendCode (http .StatusNotFound , "remoteRespPathsInfos is null" )
357+ }
358+ if pathInfo .Size > consts .MAX_HTTP_DOWNLOAD_SIZE {
359+ if resolveResp , err := f .requestFileResolve (hfUri , authorization ); err != nil {
360+ return nil , err
361+ } else {
362+ pathInfo .XXetHash = resolveResp .GetKey (consts .HUGGINGFACE_HEADER_X_XET_HASH )
363+ pathInfo .Location = resolveResp .GetKey (consts .HUGGINGFACE_LOCATION )
364+ pathInfo .Link = resolveResp .GetKey (consts .HUGGINGFACE_Link )
363365 }
364366 }
365- ret = append (ret , remoteRespPathsInfos ... )
367+ ret := []* common.PathsInfo {pathInfo }
368+ b , _ := sonic .Marshal (ret ) // 转成单个文件的切片
369+ if err = util .MakeDirs (apiPathInfoPath ); err != nil {
370+ return nil , fmt .Errorf ("create %s dir err.%v" , apiPathInfoPath , err )
371+ }
372+ if err = f .WriteCacheRequest (apiPathInfoPath , response .StatusCode , response .ExtractHeaders (response .Headers ), b ); err != nil {
373+ return nil , fmt .Errorf ("WriteCacheRequest err.%s,%v" , apiPathInfoPath , err )
374+ }
366375 }
367- return ret , nil
376+ return pathInfo , nil
368377}
369378
370- func (f * FileDao ) requestFilePath (repoType , orgRepo , commit , authorization string , filePaths []string ) (* common.Response , error ) {
371- pathsInfoUri := fmt .Sprintf ("/api/%s/%s/paths-info/%s" , repoType , orgRepo , commit )
372- response , err := f .pathsInfoProxy (pathsInfoUri , authorization , filePaths )
379+ func (f * FileDao ) requestFileResolve (fileResolveUri , authorization string ) (* common.Response , error ) {
380+ headers := map [string ]string {}
381+ if authorization != "" {
382+ headers ["authorization" ] = authorization
383+ }
384+ response , err := util .RetryRequest (func () (* common.Response , error ) {
385+ return util .Head (fileResolveUri , headers )
386+ })
373387 if err != nil {
374- zap .S ().Errorf ("req %s err.%v" , pathsInfoUri , err )
388+ zap .S ().Errorf ("req %s err.%v" , fileResolveUri , err )
375389 return nil , myerr .NewAppendCode (http .StatusInternalServerError , fmt .Sprintf ("%v" , err ))
376390 }
377- if response .StatusCode != http .StatusOK {
391+ // 非成功或重定向
392+ if response .StatusCode != http .StatusOK && ! (response .StatusCode >= http .StatusMultipleChoices && response .StatusCode <= http .StatusPermanentRedirect ) {
378393 var errorResp common.ErrorResp
379394 if len (response .Body ) > 0 {
380395 err = sonic .Unmarshal (response .Body , & errorResp )
@@ -387,7 +402,7 @@ func (f *FileDao) requestFilePath(repoType, orgRepo, commit, authorization strin
387402 return response , nil
388403}
389404
390- func (f * FileDao ) pathsInfoProxy ( targetUri , authorization string , filePaths []string ) (* common.Response , error ) {
405+ func (f * FileDao ) requestFilePathInfo ( pathsInfoUri , authorization string , filePaths []string ) (* common.Response , error ) {
391406 reqData := map [string ]interface {}{
392407 "paths" : filePaths ,
393408 }
@@ -399,9 +414,23 @@ func (f *FileDao) pathsInfoProxy(targetUri, authorization string, filePaths []st
399414 if authorization != "" {
400415 headers ["authorization" ] = authorization
401416 }
402- return util .RetryRequest (func () (* common.Response , error ) {
403- return util .Post (targetUri , "application/json" , jsonData , headers )
404- })
417+ if response , err := util .RetryRequest (func () (* common.Response , error ) {
418+ return util .Post (pathsInfoUri , "application/json" , jsonData , headers )
419+ }); err != nil {
420+ zap .S ().Errorf ("req %s err.%v" , pathsInfoUri , err )
421+ return nil , myerr .NewAppendCode (http .StatusInternalServerError , fmt .Sprintf ("%v" , err ))
422+ } else if response .StatusCode != http .StatusOK {
423+ var errorResp common.ErrorResp
424+ if len (response .Body ) > 0 {
425+ err = sonic .Unmarshal (response .Body , & errorResp )
426+ if err != nil {
427+ return nil , myerr .NewAppendCode (response .StatusCode , fmt .Sprintf ("response code %d, %v" , response .StatusCode , err ))
428+ }
429+ }
430+ return nil , myerr .NewAppendCode (response .StatusCode , errorResp .Error )
431+ } else {
432+ return response , nil
433+ }
405434}
406435
407436func (f * FileDao ) FileChunkGet (c echo.Context , taskParam * downloader.TaskParam , startPos , endPos int64 , respHeaders map [string ]string ) error {
@@ -440,6 +469,13 @@ func (f *FileDao) WriteCacheRequest(apiPath string, statusCode int, headers map[
440469 return util .WriteDataToFile (apiPath , cacheContent )
441470}
442471
472+ func (f * FileDao ) ExistApiPathFile (apiPath string ) bool {
473+ lock := f .lockDao .getMetaFileLock (apiPath )
474+ lock .RLock ()
475+ defer lock .RUnlock ()
476+ return util .FileExists (apiPath )
477+ }
478+
443479func (f * FileDao ) ReadCacheRequest (apiPath string ) (* common.CacheContent , error ) {
444480 lock := f .lockDao .getMetaFileLock (apiPath )
445481 lock .RLock ()
0 commit comments