@@ -4,15 +4,15 @@ import (
4
4
"context"
5
5
"crypto"
6
6
"encoding/json"
7
- "io"
8
- "io/fs"
9
- "path/filepath"
7
+ "net/http"
8
+ "strconv"
10
9
"strings"
11
10
12
- "github.com/spf13/afero/mem"
13
11
"golang.org/x/xerrors"
14
12
15
13
"cdr.dev/slog"
14
+ "github.com/coder/code-marketplace/api/httpapi"
15
+ "github.com/coder/code-marketplace/api/httpmw"
16
16
17
17
"github.com/coder/code-marketplace/extensionsign"
18
18
)
@@ -113,7 +113,7 @@ func (s *Signature) Manifest(ctx context.Context, publisher, name string, versio
113
113
return manifest , nil
114
114
}
115
115
116
- // Open will intercept requests for signed extensions payload.
116
+ // FileServer will intercept requests for signed extensions payload.
117
117
// It does this by looking for 'SigzipFileExtension' or p7s.sig.
118
118
//
119
119
// The signed payload and signing process is taken from:
@@ -125,61 +125,32 @@ func (s *Signature) Manifest(ctx context.Context, publisher, name string, versio
125
125
// the signature. Meaning the signature could be empty, incorrect, or a
126
126
// picture of cat and it would work. There is no signature verification.
127
127
//
128
- // - VSCode requires a signature payload to exist, but the context appear
129
- // to be somewhat optional.
130
- // Following another open source implementation, it appears the '.signature.p7s'
131
- // file must exist, but it can be empty.
132
- // The signature is stored in a '.signature.sig' file, although it is unclear
133
- // is VSCode ever reads this file.
134
- // TODO: Properly implement the p7s file, and diverge from the other open
135
- // source implementation. Ideally this marketplace would match Microsoft's
136
- // marketplace API.
137
- func (s * Signature ) Open (ctx context.Context , fp string ) (fs.File , error ) {
138
- if s .SigningEnabled () && strings .HasSuffix (filepath .Base (fp ), SigzipFileExtension ) {
139
- base := filepath .Base (fp )
140
- vsixPath := strings .TrimSuffix (base , SigzipFileExtension )
141
-
142
- // hijack this request, sign the sig manifest
143
- manifest , err := s .Storage .Open (ctx , filepath .Join (filepath .Dir (fp ), sigManifestName ))
144
- if err != nil {
145
- // If this file is missing, it means the extension was added before
146
- // signatures were handled by the marketplace.
147
- // TODO: Generate the sig manifest payload and insert it?
148
- return nil , xerrors .Errorf ("open signature manifest: %w" , err )
149
- }
150
- defer manifest .Close ()
151
-
152
- manifestData , err := io .ReadAll (manifest )
153
- if err != nil {
154
- return nil , xerrors .Errorf ("read signature manifest: %w" , err )
155
- }
156
-
157
- vsix , err := s .Storage .Open (ctx , filepath .Join (filepath .Dir (fp ), vsixPath + ".vsix" ))
158
- if err != nil {
159
- // If this file is missing, it means the extension was added before
160
- // signatures were handled by the marketplace.
161
- // TODO: Generate the sig manifest payload and insert it?
162
- return nil , xerrors .Errorf ("open signature manifest: %w" , err )
163
- }
164
- defer vsix .Close ()
128
+ // - VSCode requires a signature payload to exist, but the content is optional
129
+ // for linux users.
130
+ // For windows (maybe mac?) users, the signature must be valid, and this
131
+ // implementation will not work.
132
+ func (s * Signature ) FileServer () http.Handler {
133
+ return http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
134
+ if s .SigningEnabled () && strings .HasSuffix (r .URL .Path , SigzipFileExtension ) {
135
+ // hijack this request, return an empty signature payload
136
+ signed , err := extensionsign .IncludeEmptySignature ()
137
+ if err != nil {
138
+ httpapi .Write (rw , http .StatusInternalServerError , httpapi.ErrorResponse {
139
+ Message : "Unable to generate empty signature for extension" ,
140
+ Detail : err .Error (),
141
+ RequestID : httpmw .RequestID (r ),
142
+ })
143
+ return
144
+ }
165
145
166
- vsixData , err := io .ReadAll (vsix )
167
- if err != nil {
168
- return nil , xerrors .Errorf ("read signature manifest: %w" , err )
146
+ rw .Header ().Set ("Content-Length" , strconv .FormatInt (int64 (len (signed )), 10 ))
147
+ rw .WriteHeader (http .StatusOK )
148
+ _ , _ = rw .Write (signed )
149
+ return
169
150
}
170
151
171
- // TODO: Fetch the VSIX payload from the storage
172
- signed , err := s .SigZip (ctx , vsixData , manifestData )
173
- if err != nil {
174
- return nil , xerrors .Errorf ("sign and zip manifest: %w" , err )
175
- }
176
-
177
- f := mem .NewFileHandle (mem .CreateFile (fp ))
178
- _ , err = f .Write (signed )
179
- return f , err
180
- }
181
-
182
- return s .Storage .Open (ctx , fp )
152
+ s .Storage .FileServer ().ServeHTTP (rw , r )
153
+ })
183
154
}
184
155
185
156
func (s * Signature ) SigZip (ctx context.Context , vsix []byte , sigManifest []byte ) ([]byte , error ) {
0 commit comments