diff --git a/.gitignore b/.gitignore index dd1fdf3..20e96dc 100644 --- a/.gitignore +++ b/.gitignore @@ -24,4 +24,5 @@ dist-ssr *.sw? # php +/public/vendor /api/vendor diff --git a/api/.htaccess b/api/.htaccess deleted file mode 100644 index daad08f..0000000 --- a/api/.htaccess +++ /dev/null @@ -1,15 +0,0 @@ - - Order Allow,Deny - Deny from all - - - - RewriteEngine On - - # RewriteCond %{HTTPS} off - # RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule . index.php [L] - diff --git a/api/routes/game/details.php b/api/routes/game/details.php deleted file mode 100644 index 0dd5d69..0000000 --- a/api/routes/game/details.php +++ /dev/null @@ -1,59 +0,0 @@ - function($data, $headers, $db) { - $imagesHostName = 'https://geohry.skolazdola.cz/'; - - if(!isset($data['gameurl']) || empty($data['gameurl'])) return [ - "error" => "Property 'gameurl' is not set." - ]; - - $gameUrl = $data['gameurl']; - - $gameDetails = $db->select('games4', '*', [ - 'url' => $gameUrl - ])[0]; - - $gameDetails["questions"] = $db->select('questions4', '*', [ - 'url' => $gameUrl - ]); - - $thumbnailPath = "{$imagesHostName}/games/{$gameUrl}/intro.jpg"; - $gameDetails["thumbnail"] = remoteFileExists($thumbnailPath) ? $thumbnailPath : null; - - foreach($gameDetails["questions"] as &$question) { - $questionThumbnailPath = "{$imagesHostName}/games/{$gameUrl}/" . $question["uniqid"] . ".jpg"; - $question["thumbnail"] = remoteFileExists($questionThumbnailPath) ? $questionThumbnailPath : null; - } - - return $gameDetails; - } - -]; diff --git a/composer.json b/composer.json index 8e6fff0..ae334d7 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "config": { - "vendor-dir": "api/vendor" + "vendor-dir": "public/vendor" }, "require": { "bramus/router": "1.5", diff --git a/package-lock.json b/package-lock.json index b46d7fa..da28d06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "geohry", "version": "0.0.0", "dependencies": { + "axios": "^0.27.2", "svelte-routing": "^1.6.0" }, "devDependencies": { @@ -95,6 +96,11 @@ "node": ">= 8" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "node_modules/autoprefixer": { "version": "10.4.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", @@ -128,6 +134,15 @@ "postcss": "^8.1.0" } }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -245,6 +260,17 @@ "fsevents": "~2.3.2" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -282,6 +308,14 @@ "node": ">=0.10.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -685,6 +719,38 @@ "node": ">=8" } }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -888,6 +954,25 @@ "node": ">=12" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -1515,6 +1600,11 @@ "picomatch": "^2.0.4" } }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, "autoprefixer": { "version": "10.4.7", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.7.tgz", @@ -1529,6 +1619,15 @@ "postcss-value-parser": "^4.2.0" } }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1600,6 +1699,14 @@ "readdirp": "~3.6.0" } }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1626,6 +1733,11 @@ "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -1833,6 +1945,21 @@ "to-regex-range": "^5.0.1" } }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fraction.js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", @@ -1986,6 +2113,19 @@ "sourcemap-codec": "^1.4.8" } }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "requires": { + "mime-db": "1.52.0" + } + }, "min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", diff --git a/package.json b/package.json index 45afb62..340ddde 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "dev": "vite", "build": "vite build", "preview": "vite preview", - "php": "php -S localhost:8000 -t ./api" + "php": "php -S localhost:8000 -t ./public" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^1.0.1", @@ -20,6 +20,7 @@ "vite": "^3.0.0" }, "dependencies": { + "axios": "^0.27.2", "svelte-routing": "^1.6.0" } } diff --git a/public/.htaccess b/public/.htaccess index daad08f..833f494 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,15 +1,10 @@ - + Order Allow,Deny Deny from all - - RewriteEngine On +RewriteEngine On - # RewriteCond %{HTTPS} off - # RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule . index.php [L] - +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . index.php [L] diff --git a/api/.env b/public/api/.env similarity index 100% rename from api/.env rename to public/api/.env diff --git a/api/index.php b/public/api/index.php similarity index 87% rename from api/index.php rename to public/api/index.php index 30cef15..3fc8db0 100644 --- a/api/index.php +++ b/public/api/index.php @@ -1,11 +1,6 @@ 'mysql', 'host' => env("DB_HOST"), @@ -49,7 +42,10 @@ $getFolderContentUtil = function($dir) use($routesDirectory, &$getFolderContentU $router->{$key}(str_replace(".php", '', $pathWithoutRelativeRoot), function() use($router, $fn, $data, $error, $database) { $responseResult = $fn($data, getallheaders(), $database, $error, $router); if($responseResult) { - echo json_encode($responseResult); + $responseResult["status"] = array_key_exists("status", $responseResult) ? $responseResult["status"] : 200; + http_response_code($responseResult["status"]); + echo json_encode($responseResult["data"]); + exit(); } }); } diff --git a/public/api/routes/game/details.php b/public/api/routes/game/details.php new file mode 100644 index 0000000..3d2b55e --- /dev/null +++ b/public/api/routes/game/details.php @@ -0,0 +1,74 @@ + function($data, $headers, $db) { + function remoteFileExists($url) { + $curl = curl_init($url); + + //don't fetch the actual page, you only want to check the connection is ok + curl_setopt($curl, CURLOPT_NOBODY, true); + + //do request + $result = curl_exec($curl); + + $ret = false; + + //if request did not fail + if ($result !== false) { + //if request was ok, check response code + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + if ($statusCode == 200) { + $ret = true; + } + } + + curl_close($curl); + + return $ret; + } + + $imagesHostName = 'https://geohry.skolazdola.cz/'; + + if(!isset($data['gameurl']) || empty($data['gameurl'])) return [ + "data" => [ + "success" => false, + "message" => "Property 'gameurl' is not set." + ] + ]; + + $gameUrl = $data['gameurl']; + + $gameDetails = $db->select('games4', '*', [ + 'url' => $gameUrl + ]); + + if(!$gameDetails) return [ + "data" => [ + "success" => false, + "message" => "Invalid 'gameurl'." + ] + ]; + + $gameDetails = $gameDetails[0]; + + $gameDetails["questions"] = $db->select('questions4', '*', [ + 'url' => $gameUrl + ]); + + $thumbnailPath = "{$imagesHostName}/games/{$gameUrl}/intro.jpg"; + $gameDetails["thumbnail"] = remoteFileExists($thumbnailPath) ? $thumbnailPath : null; + + foreach($gameDetails["questions"] as &$question) { + $questionThumbnailPath = "{$imagesHostName}/games/{$gameUrl}/" . $question["uniqid"] . ".jpg"; + $question["thumbnail"] = remoteFileExists($questionThumbnailPath) ? $questionThumbnailPath : null; + } + + return [ + "success" => true, + "data" => $gameDetails + ]; + } + +]; diff --git a/api/utils/cors.php b/public/cors.php similarity index 84% rename from api/utils/cors.php rename to public/cors.php index b2c6a43..cb7bd5f 100644 --- a/api/utils/cors.php +++ b/public/cors.php @@ -1,5 +1,4 @@ setBasePath('/'); + +$router->mount("/api", function() use($router) { + require_once __DIR__ . '/api/index.php'; +}); + +$router->set404('/api(/.*)?', function() { + header('HTTP/1.1 404 Not Found'); + header('Content-Type: application/json'); + + echo json_encode([ + "message" => "Route not defined." + ]); +}); + +$router->get("/.*", function() { + header('Content-Type: text/html; charset=UTF-8'); + echo "frontend!"; +}); + + +$router->run(); diff --git a/src/lib/utils/api.js b/src/lib/utils/api.js index 2191833..fb1c0b5 100644 --- a/src/lib/utils/api.js +++ b/src/lib/utils/api.js @@ -1,13 +1,18 @@ +export const hostName = 'https://erant.cz/api' + async function send({ method, path, body, token, headers }) { - const opts = { method, headers: {} } - opts.headers['Content-Type'] = 'application/json' + const opts = { method, headers: new Headers(), mode: 'cors' } + opts.headers.append('Content-Type', 'application/json') + opts.headers.append('Access-Control-Allow-Origin', '*') if (body) { opts.body = JSON.stringify(body) } if (headers) { - opts.headers = Object.fromEntries(headers.map(({ key, value }) => [key, value])) + for (const [k, v] of Object.entries(headers)) { + opts.headers.append(k, v) + } } if (token) { @@ -53,5 +58,3 @@ export function put( ) { return send({ method: 'PUT', path, body, token, headers }) } - -export const hostName = 'http://localhost:8000' diff --git a/src/routes/game.svelte b/src/routes/game.svelte index 18de6d7..c9990e3 100644 --- a/src/routes/game.svelte +++ b/src/routes/game.svelte @@ -10,7 +10,6 @@ let assets = Array.from(Array(4).keys()).map((_, i) => `/assets/temp/kar${i + 1}.png`) ;(async () => { - console.log(api.hostName) const gameData = await api.post(`${api.hostName}/game/details`, { gameurl: 'pisek-mesto-kralovske', })