chore: refactor url creation
							parent
							
								
									f663237a16
								
							
						
					
					
						commit
						9734f707f0
					
				|  | @ -1,4 +1,4 @@ | |||
| import { fetchURL, removePrefix } from "./utils"; | ||||
| import { fetchURL, removePrefix, createURL } from "./utils"; | ||||
| import { baseURL } from "@/utils/constants"; | ||||
| import store from "@/store"; | ||||
| 
 | ||||
|  | @ -154,3 +154,33 @@ export async function checksum(url, algo) { | |||
|   const data = await resourceAction(`${url}?checksum=${algo}`, "GET"); | ||||
|   return (await data.json()).checksums[algo]; | ||||
| } | ||||
| 
 | ||||
| export function getDownloadURL(file, inline) { | ||||
|   const params = { | ||||
|     ...(inline && { inline: "true" }), | ||||
|   }; | ||||
| 
 | ||||
|   return createURL("api/raw" + file.path, params); | ||||
| } | ||||
| 
 | ||||
| export function getPreviewURL(file, size) { | ||||
|   const params = { | ||||
|     inline: "true", | ||||
|     key: Date.parse(file.modified), | ||||
|   }; | ||||
| 
 | ||||
|   return createURL("api/preview/" + size + file.path, params); | ||||
| } | ||||
| 
 | ||||
| export function getSubtitlesURL(file) { | ||||
|   const params = { | ||||
|     inline: "true", | ||||
|   }; | ||||
| 
 | ||||
|   const subtitles = []; | ||||
|   for (const sub of file.subtitles) { | ||||
|     subtitles.push(createURL("api/raw" + sub, params)); | ||||
|   } | ||||
| 
 | ||||
|   return subtitles; | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { fetchURL, removePrefix } from "./utils"; | ||||
| import { fetchURL, removePrefix, createURL } from "./utils"; | ||||
| import { baseURL } from "@/utils/constants"; | ||||
| 
 | ||||
| export async function fetch(url, password = "") { | ||||
|  | @ -59,3 +59,12 @@ export function download(format, hash, token, ...files) { | |||
| 
 | ||||
|   window.open(url); | ||||
| } | ||||
| 
 | ||||
| export function getDownloadURL(share, inline = false) { | ||||
|   const params = { | ||||
|     ...(inline && { inline: "true" }), | ||||
|     ...(share.token && { token: share.token }), | ||||
|   }; | ||||
| 
 | ||||
|   return createURL("api/public/dl/" + share.hash + share.path, params, false); | ||||
| } | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| import { fetchURL, fetchJSON, removePrefix } from "./utils"; | ||||
| import { fetchURL, fetchJSON, removePrefix, createURL } from "./utils"; | ||||
| 
 | ||||
| export async function list() { | ||||
|   return fetchJSON("/api/shares"); | ||||
|  | @ -34,3 +34,7 @@ export async function create(url, password = "", expires = "", unit = "hours") { | |||
|     body: body, | ||||
|   }); | ||||
| } | ||||
| 
 | ||||
| export function getShareURL(share) { | ||||
|   return createURL("share/" + share.hash, {}, false); | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| import store from "@/store"; | ||||
| import { renew } from "@/utils/auth"; | ||||
| import { baseURL } from "@/utils/constants"; | ||||
| import { encodePath } from "@/utils/url"; | ||||
| 
 | ||||
| export async function fetchURL(url, opts) { | ||||
|   opts = opts || {}; | ||||
|  | @ -45,3 +46,18 @@ export function removePrefix(url) { | |||
|   if (url[0] !== "/") url = "/" + url; | ||||
|   return url; | ||||
| } | ||||
| 
 | ||||
| export function createURL(endpoint, params = {}, auth = true) { | ||||
|   const url = new URL(encodePath(endpoint), origin + baseURL); | ||||
| 
 | ||||
|   const searchParams = { | ||||
|     ...(auth && { auth: store.state.jwt }), | ||||
|     ...params, | ||||
|   }; | ||||
| 
 | ||||
|   for (const key in searchParams) { | ||||
|     url.searchParams.set(key, searchParams[key]); | ||||
|   } | ||||
| 
 | ||||
|   return url.toString(); | ||||
| } | ||||
|  |  | |||
|  | @ -35,7 +35,7 @@ | |||
| </template> | ||||
| 
 | ||||
| <script> | ||||
| import { baseURL, enableThumbs } from "@/utils/constants"; | ||||
| import { enableThumbs } from "@/utils/constants"; | ||||
| import { mapMutations, mapGetters, mapState } from "vuex"; | ||||
| import filesize from "filesize"; | ||||
| import moment from "moment"; | ||||
|  | @ -58,6 +58,7 @@ export default { | |||
|     "modified", | ||||
|     "index", | ||||
|     "readOnly", | ||||
|     "path", | ||||
|   ], | ||||
|   computed: { | ||||
|     ...mapState(["user", "selected", "req", "jwt"]), | ||||
|  | @ -83,12 +84,12 @@ export default { | |||
|       return true; | ||||
|     }, | ||||
|     thumbnailUrl() { | ||||
|       const path = this.url.replace(/^\/files\//, ""); | ||||
|       const file = { | ||||
|         path: this.path, | ||||
|         modified: this.modified, | ||||
|       }; | ||||
| 
 | ||||
|       // reload the image when the file is replaced | ||||
|       const key = Date.parse(this.modified); | ||||
| 
 | ||||
|       return `${baseURL}/api/preview/thumb/${path}?k=${key}&inline=true`; | ||||
|       return api.getPreviewURL(file, "thumb"); | ||||
|     }, | ||||
|     isThumbsEnabled() { | ||||
|       return enableThumbs; | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ | |||
|             <td class="small"> | ||||
|               <button | ||||
|                 class="action copy-clipboard" | ||||
|                 :data-clipboard-text="buildLink(link.hash)" | ||||
|                 :data-clipboard-text="buildLink(link)" | ||||
|                 :aria-label="$t('buttons.copyToClipboard')" | ||||
|                 :title="$t('buttons.copyToClipboard')" | ||||
|               > | ||||
|  | @ -118,7 +118,6 @@ | |||
| <script> | ||||
| import { mapState, mapGetters } from "vuex"; | ||||
| import { share as api } from "@/api"; | ||||
| import { baseURL } from "@/utils/constants"; | ||||
| import moment from "moment"; | ||||
| import Clipboard from "clipboard"; | ||||
| 
 | ||||
|  | @ -213,8 +212,8 @@ export default { | |||
|     humanTime(time) { | ||||
|       return moment(time * 1000).fromNow(); | ||||
|     }, | ||||
|     buildLink(hash) { | ||||
|       return `${window.location.origin}${baseURL}/share/${hash}`; | ||||
|     buildLink(share) { | ||||
|       return api.getShareURL(share); | ||||
|     }, | ||||
|     sort() { | ||||
|       this.links = this.links.sort((a, b) => { | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ const theme = window.FileBrowser.Theme; | |||
| const enableThumbs = window.FileBrowser.EnableThumbs; | ||||
| const resizePreview = window.FileBrowser.ResizePreview; | ||||
| const enableExec = window.FileBrowser.EnableExec; | ||||
| const origin = window.location.origin; | ||||
| 
 | ||||
| export { | ||||
|   name, | ||||
|  | @ -31,4 +32,5 @@ export { | |||
|   enableThumbs, | ||||
|   resizePreview, | ||||
|   enableExec, | ||||
|   origin, | ||||
| }; | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| function removeLastDir(url) { | ||||
| export function removeLastDir(url) { | ||||
|   var arr = url.split("/"); | ||||
|   if (arr.pop() === "") { | ||||
|     arr.pop(); | ||||
|  | @ -9,7 +9,7 @@ function removeLastDir(url) { | |||
| 
 | ||||
| // this code borrow from mozilla
 | ||||
| // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Examples
 | ||||
| function encodeRFC5987ValueChars(str) { | ||||
| export function encodeRFC5987ValueChars(str) { | ||||
|   return ( | ||||
|     encodeURIComponent(str) | ||||
|       // Note that although RFC3986 reserves "!", RFC5987 does not,
 | ||||
|  | @ -22,7 +22,7 @@ function encodeRFC5987ValueChars(str) { | |||
|   ); | ||||
| } | ||||
| 
 | ||||
| function encodePath(str) { | ||||
| export function encodePath(str) { | ||||
|   return str | ||||
|     .split("/") | ||||
|     .map((v) => encodeURIComponent(v)) | ||||
|  | @ -30,7 +30,7 @@ function encodePath(str) { | |||
| } | ||||
| 
 | ||||
| export default { | ||||
|   encodeRFC5987ValueChars: encodeRFC5987ValueChars, | ||||
|   removeLastDir: removeLastDir, | ||||
|   encodePath: encodePath, | ||||
|   encodeRFC5987ValueChars, | ||||
|   removeLastDir, | ||||
|   encodePath, | ||||
| }; | ||||
|  |  | |||
|  | @ -104,7 +104,7 @@ | |||
|             </a> | ||||
|           </div> | ||||
|           <div class="share__box__element share__box__center"> | ||||
|             <qrcode-vue :value="fullLink" size="200" level="M"></qrcode-vue> | ||||
|             <qrcode-vue :value="link" size="200" level="M"></qrcode-vue> | ||||
|           </div> | ||||
|         </div> | ||||
|         <div | ||||
|  | @ -173,7 +173,6 @@ | |||
| <script> | ||||
| import { mapState, mapMutations, mapGetters } from "vuex"; | ||||
| import { pub as api } from "@/api"; | ||||
| import { baseURL } from "@/utils/constants"; | ||||
| import filesize from "filesize"; | ||||
| import moment from "moment"; | ||||
| 
 | ||||
|  | @ -231,21 +230,10 @@ export default { | |||
|       return "insert_drive_file"; | ||||
|     }, | ||||
|     link: function () { | ||||
|       let queryArg = ""; | ||||
|       if (this.token !== "") { | ||||
|         queryArg = `?token=${this.token}`; | ||||
|       } | ||||
| 
 | ||||
|       const path = this.$route.path.split("/").splice(2).join("/"); | ||||
|       return `${baseURL}/api/public/dl/${path}${queryArg}`; | ||||
|       return api.getDownloadURL(this.req); | ||||
|     }, | ||||
|     inlineLink: function () { | ||||
|       let url = new URL(this.fullLink); | ||||
|       url.searchParams.set("inline", "true"); | ||||
|       return url.href; | ||||
|     }, | ||||
|     fullLink: function () { | ||||
|       return window.location.origin + this.link; | ||||
|       return api.getDownloadURL(this.req, true); | ||||
|     }, | ||||
|     humanSize: function () { | ||||
|       if (this.req.isDir) { | ||||
|  | @ -287,6 +275,7 @@ export default { | |||
| 
 | ||||
|       try { | ||||
|         let file = await api.fetch(url, this.password); | ||||
|         file.hash = this.hash; | ||||
| 
 | ||||
|         this.token = file.token || ""; | ||||
| 
 | ||||
|  |  | |||
|  | @ -209,6 +209,7 @@ | |||
|             v-bind:modified="item.modified" | ||||
|             v-bind:type="item.type" | ||||
|             v-bind:size="item.size" | ||||
|             v-bind:path="item.path" | ||||
|           > | ||||
|           </item> | ||||
|         </div> | ||||
|  | @ -225,6 +226,7 @@ | |||
|             v-bind:modified="item.modified" | ||||
|             v-bind:type="item.type" | ||||
|             v-bind:size="item.size" | ||||
|             v-bind:path="item.path" | ||||
|           > | ||||
|           </item> | ||||
|         </div> | ||||
|  |  | |||
|  | @ -103,7 +103,7 @@ | |||
|             </a> | ||||
|             <a | ||||
|               target="_blank" | ||||
|               :href="downloadUrl + '&inline=true'" | ||||
|               :href="raw" | ||||
|               class="button button--flat" | ||||
|               v-if="!req.isDir" | ||||
|             > | ||||
|  | @ -145,7 +145,7 @@ | |||
| <script> | ||||
| import { mapState } from "vuex"; | ||||
| import { files as api } from "@/api"; | ||||
| import { baseURL, resizePreview } from "@/utils/constants"; | ||||
| import { resizePreview } from "@/utils/constants"; | ||||
| import url from "@/utils/url"; | ||||
| import throttle from "lodash.throttle"; | ||||
| import HeaderBar from "@/components/header/HeaderBar"; | ||||
|  | @ -186,23 +186,14 @@ export default { | |||
|       return this.nextLink !== ""; | ||||
|     }, | ||||
|     downloadUrl() { | ||||
|       return `${baseURL}/api/raw${url.encodePath(this.req.path)}?auth=${ | ||||
|         this.jwt | ||||
|       }`; | ||||
|     }, | ||||
|     previewUrl() { | ||||
|       // reload the image when the file is replaced | ||||
|       const key = Date.parse(this.req.modified); | ||||
| 
 | ||||
|       if (this.req.type === "image" && !this.fullSize) { | ||||
|         return `${baseURL}/api/preview/big${url.encodePath( | ||||
|           this.req.path | ||||
|         )}?k=${key}`; | ||||
|       } | ||||
|       return `${baseURL}/api/raw${url.encodePath(this.req.path)}?k=${key}`; | ||||
|       return api.getDownloadURL(this.req); | ||||
|     }, | ||||
|     raw() { | ||||
|       return `${this.previewUrl}&inline=true`; | ||||
|       if (this.req.type === "image" && !this.fullSize) { | ||||
|         return api.getPreviewURL(this.req, "big"); | ||||
|       } | ||||
| 
 | ||||
|       return api.getDownloadURL(this.req, true); | ||||
|     }, | ||||
|     showMore() { | ||||
|       return this.$store.state.show === "more"; | ||||
|  | @ -276,9 +267,7 @@ export default { | |||
|       } | ||||
| 
 | ||||
|       if (this.req.subtitles) { | ||||
|         this.subtitles = this.req.subtitles.map( | ||||
|           (sub) => `${baseURL}/api/raw${sub}?inline=true` | ||||
|         ); | ||||
|         this.subtitles = api.getSubtitlesURL(this.req); | ||||
|       } | ||||
| 
 | ||||
|       let dirs = this.$route.fullPath.split("/"); | ||||
|  | @ -320,15 +309,14 @@ export default { | |||
|         return; | ||||
|       } | ||||
|     }, | ||||
|     prefetchUrl: function (item) { | ||||
|       const key = Date.parse(item.modified); | ||||
|       if (item.type === "image" && !this.fullSize) { | ||||
|         return `${baseURL}/api/preview/big${item.path}?k=${key}&inline=true`; | ||||
|       } else if (item.type === "image") { | ||||
|         return `${baseURL}/api/raw${item.path}?k=${key}&inline=true`; | ||||
|       } else { | ||||
|     prefetchUrl(item) { | ||||
|       if (item.type !== "image") { | ||||
|         return ""; | ||||
|       } | ||||
| 
 | ||||
|       return this.fullSize | ||||
|         ? api.getDownloadURL(item, true) | ||||
|         : api.getPreviewURL(item, "big"); | ||||
|     }, | ||||
|     openMore() { | ||||
|       this.$store.commit("showHover", "more"); | ||||
|  | @ -358,7 +346,7 @@ export default { | |||
|       this.$router.push({ path: uri }); | ||||
|     }, | ||||
|     download() { | ||||
|       api.download(null, this.$route.path); | ||||
|       window.open(this.downloadUrl); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|  |  | |||
|  | @ -19,9 +19,7 @@ | |||
| 
 | ||||
|             <tr v-for="link in links" :key="link.hash"> | ||||
|               <td> | ||||
|                 <a :href="buildLink(link.hash)" target="_blank">{{ | ||||
|                   link.path | ||||
|                 }}</a> | ||||
|                 <a :href="buildLink(link)" target="_blank">{{ link.path }}</a> | ||||
|               </td> | ||||
|               <td> | ||||
|                 <template v-if="link.expire !== 0">{{ | ||||
|  | @ -43,7 +41,7 @@ | |||
|               <td class="small"> | ||||
|                 <button | ||||
|                   class="action copy-clipboard" | ||||
|                   :data-clipboard-text="buildLink(link.hash)" | ||||
|                   :data-clipboard-text="buildLink(link)" | ||||
|                   :aria-label="$t('buttons.copyToClipboard')" | ||||
|                   :title="$t('buttons.copyToClipboard')" | ||||
|                 > | ||||
|  | @ -64,7 +62,6 @@ | |||
| 
 | ||||
| <script> | ||||
| import { share as api, users } from "@/api"; | ||||
| import { baseURL } from "@/utils/constants"; | ||||
| import { mapState, mapMutations } from "vuex"; | ||||
| import moment from "moment"; | ||||
| import Clipboard from "clipboard"; | ||||
|  | @ -136,8 +133,8 @@ export default { | |||
|     humanTime(time) { | ||||
|       return moment(time * 1000).fromNow(); | ||||
|     }, | ||||
|     buildLink(hash) { | ||||
|       return `${window.location.origin}${baseURL}/share/${hash}`; | ||||
|     buildLink(share) { | ||||
|       return api.getShareURL(share); | ||||
|     }, | ||||
|   }, | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Ramires Viana
						Ramires Viana