File size: 11,531 Bytes
3b6bb5e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
const { execFile } = require('child_process');
const http = require('http');
const fs = require('fs');
const path = require('path');
const formidable = require('formidable'); // Ajout de formidable pour analyser les requêtes multipart/form-data

// Importer dotenv pour gérer les variables d'environnement
require('dotenv').config();

const { Storage } = require('@google-cloud/storage');

// Si la variable GOOGLE_APPLICATION_CREDENTIALS n'est pas définie, on la définit ici.
if (!process.env.GOOGLE_APPLICATION_CREDENTIALS) {
  process.env.GOOGLE_APPLICATION_CREDENTIALS = path.join(__dirname, 'service-key.json');
}

// Instancier le client Google Cloud Storage
const storage = new Storage();
const bucketName = "test3-2d896.appspot.com";

// Chemin vers le dossier contenant les fichiers statiques
const staticDir = path.join(__dirname, 'public');

// Fonction pour servir les fichiers statiques
function serveStaticFile(req, res) {
  let filePath = path.join(staticDir, req.url === '/' ? 'index.html' : req.url);

  // Normalisez le chemin pour éviter des caractères relatifs comme "../"
  filePath = path.normalize(filePath);

  // Vérifiez que le fichier demandé reste dans le dossier `public`
  if (!filePath.startsWith(staticDir)) {
    res.writeHead(403, { 'Content-Type': 'text/plain' });
    res.end('Accès refusé');
    return;
  }

  // Vérifiez si le fichier existe
  fs.stat(filePath, (err, stats) => {
    if (err || !stats.isFile()) {
      res.writeHead(404, { 'Content-Type': 'text/plain' });
      res.end('Fichier non trouvé');
      return;
    }

    // Détecte le type MIME basé sur l'extension
    const ext = path.extname(filePath).toLowerCase();
    const mimeTypes = {
      '.html': 'text/html',
      '.css': 'text/css',
      '.js': 'application/javascript',
      '.json': 'application/json',
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.svg': 'image/svg+xml',
      '.wasm': 'application/wasm',
    };
    const contentType = mimeTypes[ext] || 'application/octet-stream';

    // Lit et sert le fichier
    fs.readFile(filePath, (err, data) => {
      if (err) {
        res.writeHead(500, { 'Content-Type': 'text/plain' });
        res.end('Erreur du serveur');
        return;
      }
      res.writeHead(200, { 'Content-Type': contentType });
      res.end(data);
    });
  });
}

const server = http.createServer((req, res) => {
  // Ajouter les en-têtes CORS nécessaires pour toutes les requêtes
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

  // Gérer les requêtes OPTIONS (préflight request)
  if (req.method === 'OPTIONS') {
    res.writeHead(204);
    res.end();
    return;
  }

  // Servir les fichiers statiques pour les requêtes GET
  if (req.method === 'GET') {
    serveStaticFile(req, res);
    return;
  }

  // Endpoint : Création des données JSON pour une visite
  if (req.method === 'POST' && req.url === '/create-visite-data') {
    const bucketName = "test3-2d896.appspot.com";
    const form = new formidable.IncomingForm();
    form.parse(req, async (err, fields) => {
      if (err) {
          console.error('Erreur lors de l\'analyse de la requête :', err);
          res.writeHead(400, { 'Content-Type': 'text/plain' });
          res.end('Erreur lors de l\'analyse de la requête.');
          return;
      }
  
      try {
          console.log('Métadonnées brutes reçues :', fields.metadata); // Log des données brutes
          const metadata = JSON.parse(fields.metadata || '{}'); // Parse en JSON
          console.log('Métadonnées analysées :', metadata);
      } catch (parseError) {
          console.error('Erreur lors du parsing JSON :', parseError);
          res.writeHead(400, { 'Content-Type': 'text/plain' });
          res.end('Erreur dans le format du JSON envoyé.');
      }
  });
  

    return;
  }

  if (req.method === 'POST' && req.url === '/upload-to-gcs') {
    let body = '';

    req.on('data', chunk => {
      body += chunk.toString(); // Convertir les chunks en chaîne
    });

    req.on('end', () => {
      try {
        // Analysez le corps de la requête en JSON
        const { folderPath, jsonData } = JSON.parse(body);

        // Loguer le chemin du dossier et les données pour voir ce qui est reçu
        console.log('Chemin du dossier:', folderPath);
        console.log('Données JSON:', JSON.stringify(jsonData, null, 2));

        // Chemin vers le script local_script.js
        const scriptPath = path.resolve(__dirname, 'local_script.js');  // Utilisez path.resolve pour obtenir un chemin absolu
        console.log(`Chemin absolu du script : ${scriptPath}`);

        // Exécuter le script Node.js avec les paramètres appropriés
        const args = [folderPath, JSON.stringify(jsonData)];

        console.log(`Commande exécutée : node ${scriptPath} ${args.join(' ')}`); // Affichez la commande exécutée pour vérification

        // Augmentez maxBuffer si nécessaire pour éviter les problèmes liés à la taille des logs
        execFile('node', [scriptPath, ...args], { maxBuffer: 1024 * 1024 * 50 }, (error, stdout, stderr) => {
          if (error) {
            console.error(`Erreur lors de l'exécution de local_script.js :`, error);
            console.error(`stderr:`, stderr);
            res.writeHead(500, { 'Content-Type': 'text/plain' });
            res.end('Erreur lors du téléversement.');
            return; // Sortir pour éviter un double envoi
          } else {
            console.log(`Téléversement réussi : ${stdout}`);
            res.writeHead(200, { 'Content-Type': 'text/plain' });
            res.end('Fichier téléversé avec succès vers Google Cloud Storage.');
          }
        });
      } catch (parseError) {
        console.error('Erreur lors de la lecture du corps de la requête:', parseError);
        res.writeHead(400, { 'Content-Type': 'text/plain' });
        res.end('Erreur de format du corps de la requête.');
      }
    });

    return; // Sortir après avoir traité cette route
  }
  if (req.method === 'POST' && req.url === '/create-visit') {
    const form = new formidable.IncomingForm();
    form.multiples = true;
    form.uploadDir = './uploads';

    if (!fs.existsSync(form.uploadDir)) {
        fs.mkdirSync(form.uploadDir, { recursive: true });
    }

    const bucketName = "test3-2d896.appspot.com";

    form.parse(req, async (err, fields, files) => {
      if (err) {
          console.error('Erreur lors de l\'analyse de la requête :', err);
          res.writeHead(400, { 'Content-Type': 'text/plain' });
          res.end('Erreur lors de l\'analyse de la requête.');
          return;
      }
  
      try {
          const metadata = JSON.parse(fields.metadata || '{}');
          const { jsonData } = metadata;
  
          console.log('Données JSON reçues :', jsonData);
          const folderName = jsonData.folderName;
  
          if (!folderName) {
              throw new Error("Nom de dossier (folderName) manquant ou incorrect.");
          }
  
          console.log('Nom du dossier pour les fichiers téléversés :', folderName);
  
          const uploadedFiles = Array.isArray(files.files) ? files.files : [files.files];
          const uploadedUrls = [];
  
          for (const file of uploadedFiles) {
              const destinationPath = `${folderName}/${file.originalFilename}`;
              console.log(`Téléversement du fichier : ${destinationPath}`);
  
              await storage.bucket(bucketName).upload(file.filepath, {
                  destination: destinationPath,
                  metadata: {
                      contentType: file.mimetype,
                  },
              });
  
              uploadedUrls.push(`https://storage.googleapis.com/${bucketName}/${destinationPath}`);
          }
  
          jsonData.mediaUrls = uploadedUrls;
  
          const jsonFilePath = `${folderName}/visit_data.json`;
          const jsonBuffer = Buffer.from(JSON.stringify(jsonData, null, 2));
  
          console.log(`Téléversement du fichier JSON : ${jsonFilePath}`);
          await storage.bucket(bucketName).file(jsonFilePath).save(jsonBuffer, {
              contentType: 'application/json',
          });
  
          console.log('Fichiers et données téléversés avec succès.');
  
          res.writeHead(200, { 'Content-Type': 'application/json' });
          res.end(JSON.stringify({
              success: true,
              message: 'Données de la visite téléversées avec succès.',
              jsonFilePath,
          }));
      } catch (error) {
          console.error('Erreur lors du traitement des données :', error);
          res.writeHead(500, { 'Content-Type': 'text/plain' });
          res.end('Erreur lors du traitement des données.');
      }
  });
  

    return;
}




  // Route pour générer une URL signée
  if (req.method === 'POST' && req.url === '/generate-signed-url') {
    let body = '';

    req.on('data', chunk => {
      body += chunk.toString();
    });

    req.on('end', async () => {
      try {
        // Extraire le `dirUrl` du corps de la requête
        const { dirUrl } = JSON.parse(body);

        if (!dirUrl) {
          res.writeHead(400, { 'Content-Type': 'text/plain' });
          res.end('dirUrl est manquant');
          return;
        }

        // Nettoyer les segments relatifs du chemin avant de générer l'URL signée
        const cleanedDirUrl = dirUrl.replace(/\/?\.\.\//g, ''); 
        const bucketName = 'test3-2d896.appspot.com';
        const filePath = `users/visite_3D/${cleanedDirUrl}`; // Utiliser le chemin nettoyé sans encodage

        const options = {
          version: 'v4',
          action: 'read',
          expires: Date.now() + 15 * 60 * 1000, // URL valable pour 15 minutes
        };

        // Générer une URL signée (GCS s'occupe de l'encodage)
        const [url] = await storage.bucket(bucketName).file(filePath).getSignedUrl(options);

        console.log(`URL signée générée : ${url}`);

        // Répondre avec l'URL signée
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.end(JSON.stringify({ url }));

      } catch (error) {
        console.error('Erreur lors de la génération de l\'URL signée:', error);
        res.writeHead(500, { 'Content-Type': 'text/plain' });
        res.end('Erreur lors de la génération de l\'URL signée.');
      }
    });
    return;
  }

  // Nouvelle route pour obtenir le GCS token
  if (req.method === 'GET' && req.url === '/get-gcs-token') {
    try {
      // Générez ou récupérez le token GCS ici
      const gcsToken = '9be5e912-95e8-4e13-841e-8be3bf99505d'; // Remplacez cela par la méthode de génération dynamique si nécessaire

      // Répondre avec le token
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ token: gcsToken }));
    } catch (error) {
      console.error('Erreur lors de la récupération du jeton GCS:', error);
      res.writeHead(500, { 'Content-Type': 'text/plain' });
      res.end('Erreur lors de la récupération du jeton GCS.');
    }
    return;
  }
  

  // Si aucune des routes n'est trouvée, envoyer une réponse 404
  res.writeHead(404, { 'Content-Type': 'text/plain' });
  res.end('Route non trouvée');
});

server.listen(7860, () => {
  console.log('Serveur en écoute sur le port 7860');
});