Spaces:
Paused
Paused
Download app.js from rynekoo/playwright: direct link, hf CLI and curl.
- Browser
- Download file 7.99 kB
-
https://huggingface.co/spaces/rynekoo/playwright/resolve/main/app.js
- Command line
-
hf download hf://spaces/rynekoo/playwright/app.js
-
curl -L -o app.js https://huggingface.co/spaces/rynekoo/playwright/resolve/main/app.js
7.99 kB
| const express = require('express'); | |
| const { chromium } = require('playwright'); | |
| const cors = require('cors'); | |
| const { NodeVM } = require('vm2'); | |
| const axios = require('axios'); | |
| const app = express(); | |
| const PORT = process.env.PORT || 7860; | |
| app.set('json spaces', 2); | |
| app.use(cors()); | |
| app.use(express.json()); | |
| app.use(express.urlencoded({ extended: true })); | |
| app.use((req, res, next) => { | |
| console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`); | |
| next(); | |
| }); | |
| app.get('/', (req, res) => { | |
| res.json({ | |
| success: true, | |
| endpoints: { | |
| playwright_v1: 'POST /v1', | |
| playwright_v2: 'POST /v2', | |
| playwright_v3: 'POST /v3' | |
| }, | |
| timestamp: new Date().toISOString() | |
| }); | |
| }); | |
| app.post('/v1', async (req, res) => { | |
| const { code, timeout = 300000 } = req.body; | |
| if (!code) { | |
| return res.status(400).json({ | |
| error: { | |
| message: 'Code is required', | |
| type: 'invalid_request_error' | |
| } | |
| }); | |
| } | |
| let output = []; | |
| const originalLog = console.log; | |
| console.log = (...args) => { | |
| const message = args.map(arg => (typeof arg === 'object' ? JSON.stringify(arg) : arg)).join(' '); | |
| output.push(message); | |
| originalLog.apply(console, args); | |
| }; | |
| const vm = new NodeVM({ | |
| console: 'inherit', | |
| sandbox: {}, | |
| require: { | |
| external: true, | |
| builtin: ['fs', 'path'], | |
| root: './', | |
| mock: { | |
| playwright: { chromium }, | |
| }, | |
| }, | |
| }); | |
| const script = ` | |
| module.exports = async () => { | |
| ${code} | |
| }; | |
| `; | |
| let runCode; | |
| try { | |
| runCode = vm.run(script, 'sandbox.js'); | |
| } catch (error) { | |
| console.log = originalLog; | |
| return res.status(500).json({ | |
| error: { | |
| message: 'Failed to run code', | |
| details: error.message, | |
| type: 'execution_error' | |
| } | |
| }); | |
| } | |
| try { | |
| await runCode(); | |
| const startTime = Date.now(); | |
| while (output.length === 0 && Date.now() - startTime < timeout) { | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| } | |
| const result = output.length > 0 ? output.pop() : 'No output found.'; | |
| console.log = originalLog; | |
| res.json({ data: result }); | |
| } catch (err) { | |
| console.log = originalLog; | |
| res.status(500).json({ | |
| error: { | |
| message: 'Error while executing code', | |
| details: err.message, | |
| type: 'execution_error' | |
| } | |
| }); | |
| } | |
| }); | |
| app.post('/v2', async (req, res) => { | |
| const { code, timeout = 300000 } = req.body; | |
| if (!code) { | |
| return res.status(400).json({ | |
| error: { | |
| message: 'Code is required', | |
| type: 'invalid_request_error' | |
| } | |
| }); | |
| } | |
| let output = []; | |
| const originalLog = console.log; | |
| console.log = (...args) => { | |
| const message = args.map(arg => (typeof arg === 'object' ? JSON.stringify(arg) : arg)).join(' '); | |
| output.push(message); | |
| originalLog.apply(console, args); | |
| }; | |
| let runCode; | |
| try { | |
| runCode = eval(` | |
| (async () => { | |
| ${code} | |
| })(); | |
| `); | |
| } catch (error) { | |
| console.log = originalLog; | |
| return res.status(500).json({ | |
| error: { | |
| message: 'Failed to run code', | |
| details: error.message, | |
| type: 'execution_error' | |
| } | |
| }); | |
| } | |
| try { | |
| await runCode; | |
| const startTime = Date.now(); | |
| while (output.length === 0 && Date.now() - startTime < timeout) { | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| } | |
| const result = output.length > 0 ? output.pop() : 'No output found.'; | |
| console.log = originalLog; | |
| res.json({ data: result }); | |
| } catch (err) { | |
| console.log = originalLog; | |
| res.status(500).json({ | |
| error: { | |
| message: 'Error while executing code', | |
| details: err.message, | |
| type: 'execution_error' | |
| } | |
| }); | |
| } | |
| }); | |
| app.post('/v3', async (req, res) => { | |
| const { code, language = 'javascript' } = req.body; | |
| if (!code) { | |
| return res.status(400).json({ | |
| error: { | |
| message: 'Code is required', | |
| type: 'invalid_request_error' | |
| } | |
| }); | |
| } | |
| const MAX_RETRIES = 3; | |
| let lastMessage = null; | |
| let lastDetails = null; | |
| for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) { | |
| try { | |
| const { data: cf } = await axios.post('https://rynekoo-cf.hf.space/action', { | |
| url: 'https://try.playwright.tech/', | |
| siteKey: '0x4AAAAAAA_K0T_2LZ0rgUtv', | |
| mode: 'turnstile-min' | |
| }); | |
| if (!cf?.data?.token) throw new Error('Failed to get cf token.'); | |
| const { data } = await axios.post('https://try.playwright.tech/service/control/run', { | |
| code, | |
| language, | |
| token: cf.data.token | |
| }, { | |
| headers: { | |
| origin: 'https://try.playwright.tech', | |
| referer: 'https://try.playwright.tech/', | |
| 'user-agent': 'Mozilla/5.0 (Linux; Android 15; SM-F958 Build/AP3A.240905.015) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.86 Mobile Safari/537.36' | |
| } | |
| }); | |
| const isTimeout = data?.error === 'Execution timeout!'; | |
| const isProtocolError = typeof data?.output === 'string' && data.output.includes('Protocol error'); | |
| if ((isTimeout || isProtocolError) && attempt < MAX_RETRIES) { | |
| lastMessage = data?.error || 'Error while executing code'; | |
| lastDetails = data?.output || null; | |
| continue; | |
| } | |
| return res.json({ data: data.output }); | |
| } catch (error) { | |
| const errData = error.response?.data; | |
| const isTimeout = errData?.error === 'Execution timeout!'; | |
| const isProtocolError = typeof errData?.output === 'string' && errData.output.includes('Protocol error'); | |
| lastMessage = errData?.error || 'Error while executing code'; | |
| lastDetails = errData?.output || null; | |
| if ((isTimeout || isProtocolError) && attempt < MAX_RETRIES) { | |
| continue; | |
| } | |
| return res.status(500).json({ | |
| error: { | |
| message: lastMessage, | |
| details: lastDetails, | |
| type: 'execution_error' | |
| } | |
| }); | |
| } | |
| } | |
| res.status(500).json({ | |
| error: { | |
| message: lastMessage, | |
| details: lastDetails, | |
| type: 'execution_error' | |
| } | |
| }); | |
| }); | |
| app.use((err, req, res, next) => { | |
| console.error('Error:', err.message); | |
| res.status(err.status || 500).json({ | |
| error: { | |
| message: err.message || 'Internal server error', | |
| type: 'api_error' | |
| } | |
| }); | |
| }); | |
| app.use((req, res) => { | |
| res.status(404).json({ | |
| error: { | |
| message: 'Not found', | |
| type: 'invalid_request_error' | |
| } | |
| }); | |
| }); | |
| function startServer() { | |
| app.listen(PORT, () => { | |
| console.log(`Playwright API Server running on http://localhost:${PORT}`); | |
| console.log('\nAvailable endpoints:'); | |
| console.log(` POST http://localhost:${PORT}/v1`); | |
| console.log(` POST http://localhost:${PORT}/v2`); | |
| console.log(` POST http://localhost:${PORT}/v3`); | |
| }); | |
| } | |
| process.on('SIGINT', () => { | |
| console.log('\nShutting down...'); | |
| process.exit(0); | |
| }); | |
| startServer(); |